SpringMVC初始化流程及请求流程

SpringMVC初始化流程:

初始化流程

  1. 初始化DispatcherServlet;前端控制器
  2. initMultipartResolver;分段文件解析器
  3. initLocaleResolver;本地化解析策略
  4. initThemeResolver;主题解析器
  5. initHandlerMappings;处理器映射
  6. initHandlerAdapters;控制适配器
  7. initHandlerExceptionResolvers;//如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
  8. initRequestToViewNameTranslator;//直接解析请求到视图名
  9. initViewResolvers;视图解析器
  10. initFlashMapManager;flash映射管理器

源码

1. 继承关系

Servlet------>GenericServlet------->HttpServlet------->HttpServletBean------->FramworkServlet
-------->DispatcherServlet

2. 源码分析

1.Servlet接口:

public void init(ServletConfig config) throws ServletException; 

2.GenericServlet : abstract class抽象类 实现了初始化方法。

    public void init(ServletConfig config) throws ServletException {  
    this.config = config;  
    this.init();  
       } 
    调用了空方法
    public void init() throws ServletException {  

    }  

3.HttpServlet 没有对初始化相关的方法进行覆盖

4.HttpServletBean 抽象类HttpServletBean 重写了init()方法。

@Override  
public final void init() throws ServletException {  
    if (logger.isDebugEnabled()) {  
        logger.debug("Initializing servlet '" + getServletName() + "'");  
    }  

    // Set bean properties from init parameters.  
    try {  
        PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);  
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);  
        ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());  
        bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));  
        initBeanWrapper(bw);  
        bw.setPropertyValues(pvs, true);  
    }  
    catch (BeansException ex) {  
        logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);  
        throw ex;  
    }  

    // Let subclasses do whatever initialization they like.  
    initServletBean();  

    if (logger.isDebugEnabled()) {  
        logger.debug("Servlet '" + getServletName() + "' configured successfully");  
    }  
}
同时调用了
protected void initServletBean() throws ServletException {  
} 

5.FrameworkServlet

果不其然的重写了上边留空的方法 initServletBean() 它提供了整合web javabean和spring application context的整合方案

@Override  
protected final void initServletBean() throws ServletException {  
    getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");  
    if (this.logger.isInfoEnabled()) {  
        this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");  
    }  
    long startTime = System.currentTimeMillis();  

    try {  
        this.webApplicationContext = initWebApplicationContext();  
        initFrameworkServlet();  
    }  
    catch (ServletException ex) {  
        this.logger.error("Context initialization failed", ex);  
        throw ex;  
    }  
    catch (RuntimeException ex) {  
        this.logger.error("Context initialization failed", ex);  
        throw ex;  
    }  

    if (this.logger.isInfoEnabled()) {  
        long elapsedTime = System.currentTimeMillis() - startTime;  
        this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +  
                elapsedTime + " ms");  
    }  
}  

在这个方法中最重要的就是调用了一个 initWebApplicationContext()

protected WebApplicationContext initWebApplicationContext() {  
    WebApplicationContext rootContext =  
            WebApplicationContextUtils.getWebApplicationContext(getServletContext());  
    WebApplicationContext wac = null;  

    if (this.webApplicationContext != null) {  
        // A context instance was injected at construction time -> use it  
        wac = this.webApplicationContext;  
        if (wac instanceof ConfigurableWebApplicationContext) {  
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;  
            if (!cwac.isActive()) {  
                // The context has not yet been refreshed -> provide services such as  
                // setting the parent context, setting the application context id, etc  
                if (cwac.getParent() == null) {  
                    // The context instance was injected without an explicit parent -> set  
                    // the root application context (if any; may be null) as the parent  
                    cwac.setParent(rootContext);  
                }  
                configureAndRefreshWebApplicationContext(cwac);  
            }  
        }  
    }  
    if (wac == null) {  
        // No context instance was injected at construction time -> see if one  
        // has been registered in the servlet context. If one exists, it is assumed  
        // that the parent context (if any) has already been set and that the  
        // user has performed any initialization such as setting the context id  
        wac = findWebApplicationContext();  
    }  
    if (wac == null) {  
        // No context instance is defined for this servlet -> create a local one  
        wac = createWebApplicationContext(rootContext);  
    }  

    if (!this.refreshEventReceived) {  
        // Either the context is not a ConfigurableApplicationContext with refresh  
        // support or the context injected at construction time had already been  
        // refreshed -> trigger initial onRefresh manually here.  
        onRefresh(wac);  
    }  

    if (this.publishContext) {  
        // Publish the context as a servlet context attribute.  
        String attrName = getServletContextAttributeName();  
        getServletContext().setAttribute(attrName, wac);  
        if (this.logger.isDebugEnabled()) {  
            this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +  
                    "' as ServletContext attribute with name [" + attrName + "]");  
        }  
    }  

    return wac;  
} 

在这里调用了 onRefresh()

protected void onRefresh(ApplicationContext context)  {  
} 

6.DispatcherServlet 重写onRefresh方法

@Override  
protected void onRefresh(ApplicationContext context) {  
    initStrategies(context);  
}  

调用了 initStrategies(context)

protected void initStrategies(ApplicationContext context) {  
    initMultipartResolver(context);//分段文件解析器
    initLocaleResolver(context);//  本地化解析策略
    initThemeResolver(context); // 主题解析器
    initHandlerMappings(context); // 处理器映射
    initHandlerAdapters(context);  //控制适配器
    initHandlerExceptionResolvers(context);  //如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
    initRequestToViewNameTranslator(context);  //直接解析请求到视图名
    initViewResolvers(context);  //视图解析器
    initFlashMapManager(context);  //flash映射管理器
}  

用户请求流程:


用户发送请求-------------》DispatcherServlet(前端控制器)----------------》HandlerMapping(映射处理器返回Handler
将Handler传给映射适配器)------------------>HandlerAdapter(映射适配器)-------------------》
Controller(调用Handler返回ModelAndView)------------>View...ViewResolver(视图解析)---------》Model...View(
视图渲染)---------------》返回响应


  1. 用户发送请求给DispatcherServlet(前端控制器)
  2. DispatcherServlet调用HandlerMapping(映射处理器返回Handler)
  3. DispatcherServlet调用andlerAdapter(映射适配器)(传入Handler)返回(ModelAndView)
  4. DispatcherServlet调用ViewResolver(视图解析)返回(View)
  5. DispatcherServlet调用-->Model...View(视图渲染)
  6. 返回响应

你可能感兴趣的:(SpringMVC初始化流程及请求流程)