SpringMVC 源碼解析

前言

        年初面試時接觸到一道面試題,在聊到SpringMVC時提到了SpringMVC的開發者爲什麼要設計父子容器呢,又或者說是父子容器的設計有什麼更實際的做用呢?
         首先要理解對於一個web應用,當其部署在web容器上時,容器會爲其提供一個全局上下文環境ServletContext,這個上下文環境將爲後續的Spring提供宿主環境。php

SpringMVC工做流程

20180708224853769.png

DispatcherServlet上下文繼承關係

mvc-context-hierarchy.png

SpringMVC設計的父子容器

父子容器配置文件

--在web.xml中配置,兩個重要的xml:applicationContext.xml和SpringMVC-conf.xml
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:applictionContext.xml</param-value>
</context-param>
<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
  
<servlet>
    <servlet-name>dispatcher-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:springMVC-conf.xml</param-value>
    </init-param>
</servlet>
  
<servlet-mapping>
  <servlet-name>dispatcher-servlet</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

父子容器的設計目的

     根據SpringMVC的官方解釋,父(根)容器主要包括一些基礎腳手架的bean,好比Pool、DataSource、Dao、Service。目的是在不一樣的Servlet實例之間共享。這些不一樣的bean能夠在子容器中重寫。
     而子容器主要包括一些Controller、View等一些web相關的bean。 html

DispatcherServlet源碼分析

     既然SpringMVC中同時包含Spring容器和SpringMVC容器,那麼這兩個容器都是在何時初始化呢?java

根容器初始化

      首先,根容器是經過ServletContext監聽器進行建立,默認的監聽器爲ContextLoaderListener,當web應用啓動時,會調用監聽器的contextInitialized方法。
      那麼根容器的初始化就從ContextLoaderListener類提及吧,,Spring官方對該類的描述是啓動監聽器去啓動和關閉Spring的root WebApplicationContext(翻譯的實在有點蹩腳)。
     phpcode1535985292mZsXwg.gifweb

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    public ContextLoaderListener() {
    }

    public ContextLoaderListener(WebApplicationContext context) {
        super(context);
    }

    //===初始化root WebApplicationContext===
    @Override
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}

   

//ContextLoader.java
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    //初始化Spring容器時若是發現servlet 容器中已存在根Spring容根器則拋出異常,證實rootWebApplicationContext只能有一個。
    if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
        throw new IllegalStateException(
                "Cannot initialize context because there is already a root application context present - " +
                "check whether you have multiple ContextLoader* definitions in your web.xml!");
    }

    try {
        //建立webApplicationContext實例
        if (this.context == null) {
            this.context = createWebApplicationContext(servletContext);
        }
        if (this.context instanceof ConfigurableWebApplicationContext) {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
            if (!cwac.isActive()) {
                if (cwac.getParent() == null) {
                    ApplicationContext parent = loadParentContext(servletContext);
                    cwac.setParent(parent);
                }
                //配置WebApplicationContext
                configureAndRefreshWebApplicationContext(cwac, servletContext);
            }
        }
        
        /**
           把生成的webApplicationContext設置成root WebApplicationContext。保存在ServletContext上下文中。
           下一步初始化MVC ApplicationContext時須要從ServletContext取出根上下文做爲其父上下文。
        **/ 
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
        if (ccl == ContextLoader.class.getClassLoader()) {
            currentContext = this.context;
        }
        else if (ccl != null) {
            currentContextPerThread.put(ccl, this.context);
        }
        
        return this.context;
    }
    catch (RuntimeException | Error ex) {
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
        throw ex;
    }
}

      以上代碼主要完成兩個功能:建立實例WebApplicationContext實例、把所建立的WebApplicationContext設置爲根上下文,也就是設置成爲ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。面試

MVC容器初始化 

      你們知道Servlet生命週期都是從init方法開始,desctory方法結束,由jvm負責垃圾回收。而DispatcherServlet也是一個普通的Servlet,先看一下DispatcherServlet的繼承關係圖,對整個繼承關係有個瞭解。
1946613-f6892f5c658de75c.jpg
   既然提及Servlet,那就從Servlet的初始化(init)方法入手spring

//HttpServletBean.java
@Override
public final void init() throws ServletException {

    PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
    if (!pvs.isEmpty()) {
        try {
            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) {
            throw ex;
        }
    }

    //交給子類重寫
    initServletBean();
}

//FrameworkServlet.java
@Override
protected final void initServletBean() throws ServletException {
    try {
        this.webApplicationContext = initWebApplicationContext();
        initFrameworkServlet();
    }
    catch (ServletException | RuntimeException ex) {
        throw ex;
    }
}

//FrameworkServlet.java
//初始化MVC容器
protected WebApplicationContext initWebApplicationContext() {
    //從ServletContext取出根上下文
    WebApplicationContext rootContext =
            WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    WebApplicationContext wac = null;

    if (this.webApplicationContext != null) {
        wac = this.webApplicationContext;
        if (wac instanceof ConfigurableWebApplicationContext) {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
            if (!cwac.isActive()) {
                if (cwac.getParent() == null) {
                    cwac.setParent(rootContext);
                }
                configureAndRefreshWebApplicationContext(cwac);
            }
        }
    }
    if (wac == null) {
        wac = findWebApplicationContext();
    }
    
    //若是尚未webApplicatioinContext,建立webApplicationContext
    if (wac == null) {
        wac = createWebApplicationContext(rootContext);
    }

    //子類自定義對servlet子上下文後續操做,在DispatcherServlet中實現
    if (!this.refreshEventReceived) {
        synchronized (this.onRefreshMonitor) {
            //執行子類擴展方法onRefresh,在DispatcherServlet內初始化全部web相關組件
            onRefresh(wac);
        }
    }

    //發佈servlet子上下文到ServletContext
    if (this.publishContext) {
        String attrName = getServletContextAttributeName();
        //將servlet子上下文以org.springframework.web.servlet.FrameworkServlet.CONTEXT. + servletName的屬性名稱註冊到ServletContext中
        getServletContext().setAttribute(attrName, wac);
    }

    return wac;
}

protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
    return createWebApplicationContext((ApplicationContext) parent);
}

protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
    //獲取WebApplicationContext實現類,此處其實就是XmlWebApplicationContext
    Class<?> contextClass = getContextClass();
    if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
        throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +
                "': custom WebApplicationContext class [" + contextClass.getName() +
                "] is not of type ConfigurableWebApplicationContext");
    }
    
    //生成XmlWebApplicationContext實例
    ConfigurableWebApplicationContext wac =
            (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

    wac.setEnvironment(getEnvironment());
    //設置根容器爲父容器 
    wac.setParent(parent);
    String configLocation = getContextConfigLocation();
    if (configLocation != null) {
        //設置配置文件
        wac.setConfigLocation(configLocation);
    }
    
    //配置webApplicationContext
    configureAndRefreshWebApplicationContext(wac);

    return wac;
}

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
    if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
        if (this.contextId != null) {
            wac.setId(this.contextId);
        }
        else {
            wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
        }
    }

    wac.setServletContext(getServletContext());
    wac.setServletConfig(getServletConfig());
    wac.setNamespace(getNamespace());
    wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

    ConfigurableEnvironment env = wac.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
        ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
    }

    postProcessWebApplicationContext(wac);
    applyInitializers(wac);
    
    //開始處理bean
    wac.refresh();
}

      上面的關鍵代碼都在FrameworkServlet類中,有幾個關鍵點:取除根上下文,建立子上下文並設置父上下文,完成刷新,把子上下文發佈到ServletContext中。 到這裏能夠說子容器(子上下文)已經建立完成。 並把其餘初始化web組件的相關工做交給onRefresh方法完成,由DispatcherServlet來重寫onRefresh方法,這就又回到了咱們熟悉的initStrategies方法。mvc

web組件初始化

 

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

protected void initStrategies(ApplicationContext context) {
    //文件上傳解析器
    initMultipartResolver(context);
    
    //本地化解析器
    initLocaleResolver(context);
    
    //主題解析器
    initThemeResolver(context);
    
    //處理器映射器(url和Controller方法的映射)
    initHandlerMappings(context);
    
    //處理器適配器(實際執行Controller方法)
    initHandlerAdapters(context);
    
    //處理器異常解析器
    initHandlerExceptionResolvers(context);
    
    //RequestToViewName解析器
    initRequestToViewNameTranslator(context);
    
    //視圖解析器(視圖的匹配和渲染)
    initViewResolvers(context);
    
    //FlashMap管理者
    initFlashMapManager(context);
}

             這裏咱們主要關注一下三個重要組件:HandlerMapping、HandlerAdapter、ViewResolver。分析這3個組件以前,咱們先看一下咱們的springMVC-conf.xml配置文件,mvc的配置文件中,咱們配置了兩行代碼:app

<context:component-scan base-package="com.zhangfei"/>
<mvc:annotation-driven>

      第二行代碼主要是添加了默認的HandleMapping,ViewResolver,HandleAdapter。咱們看看annotation-driven的源碼定義,根據spring自定義schema定義,咱們找到以下代碼,如圖所示:
QQ截圖20190822131726.jpg
該文件就一行代碼:cors

http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
//MVC全部的標籤解析器都定義在此
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
        registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
        registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
        registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
        registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
        registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
        registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
        registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    }
}

那麼經過分析AnnotationDrivenBeanDefinitionParser類,主要完成如下三大組件的裝配工做:
QQ截圖20190822132044.jpgjvm

初始化處理器映射器

private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;

    //這裏detectAllHandlerMappings默認值爲true,能夠經過配置文件設置爲false
    if (this.detectAllHandlerMappings) {
        //從上下文(包含父上下文)中查找全部HandlerMapping實現類
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrderComparator.sort(this.handlerMappings);
        }
    }
    else {
        try {
            //這裏只取固定的bean
            HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
            this.handlerMappings = Collections.singletonList(hm);
        }
        catch (NoSuchBeanDefinitionException ex) {
            
        }
    }
    
    /***
      確保至少有一個HandlerMapping,若是沒能找到,註冊一個默認的
      默認規則在DispatcherServlet.properties中,這裏也就是取BeanNameUrlHandlerMapping、RequestMappingHandlerMapping
    ***/
    if (this.handlerMappings == null) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);     
    }
}

初始化處理器適配器

private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;

    if (this.detectAllHandlerAdapters) {
        //從上下文(包括父上下文)中查找全部HandlerAdapter實現類
        Map<String, HandlerAdapter> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        }
    }
    else {
        try {
            //這裏取bean名字爲handlerAdapter,類型爲HandlerAdapter的處理器適配器
            HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
            this.handlerAdapters = Collections.singletonList(ha);
        }
        catch (NoSuchBeanDefinitionException ex) {
            
        }
    }
    
    /**
    若是沒找到,則從默認規則裏取出指定的三個實現類:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter
    **/
    if (this.handlerAdapters == null) {
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);     
    }
}

初始化試圖解析器

private void initViewResolvers(ApplicationContext context) {
    this.viewResolvers = null;

    if (this.detectAllViewResolvers) {
        //從上下文(包括父上下文)中查找全部ViewResolver實現類
        Map<String, ViewResolver> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.viewResolvers = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrderComparator.sort(this.viewResolvers);
        }
    }
    else {
        try {
            ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
            this.viewResolvers = Collections.singletonList(vr);
        }
        catch (NoSuchBeanDefinitionException ex) {
            
        }
    }
    
    /**
    若是沒找到,則從默認規則裏取出指定的實現類:InternalResourceViewResolver
    **/
    if (this.viewResolvers == null) {
        this.viewResolvers = getDefaultStrategies(context, ViewResolver.class); 
    }
}

         三大組件的初始化最後判斷爲NULL時都會調用getDefaultStrategies方法,也就是從DispatcherServlet.properties中取出指定默認值。

protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
    String key = strategyInterface.getName();
    String value = defaultStrategies.getProperty(key);
    if (value != null) {
        String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
        List<T> strategies = new ArrayList<>(classNames.length);
        for (String className : classNames) {
            try {
                Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
                Object strategy = createDefaultStrategy(context, clazz);
                strategies.add((T) strategy);
            }
            catch (ClassNotFoundException ex) {
                throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className +"] for interface [" + key + "]", ex);
            }
            catch (LinkageError err) {
                throw new BeanInitializationException("Unresolvable class definition for DispatcherServlet's default strategy class [" +className + "] for interface [" + key + "]", err);
            }
        }
        return strategies;
    }
    else {
        return new LinkedList<>();
    }
}

DispatcherServlet請求處理過程

     提到請求處理過程,咱們再來回顧一下Servlet生命週期,處理請求都放在service方法中處理,那麼也從DispatcherServlet的service方法入手。DispatcherServlet繼承FrameworkServlet,在FrameworkServlet中重寫了service、doGet、doPost、doPut、doDelete方法。

//FrameworkServlet.java
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
        processRequest(request, response);
    }
    else {
        super.service(request, response);
    }
}

    
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}

    
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}

    
@Override
protected final void doPut(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}

    
@Override
protected final void doDelete(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}


protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;

    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContext localeContext = buildLocaleContext(request);

    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
    
    //把新構造的LocaleContext對象和ServletRequestAttributes對象和當前請求線程綁定(後面要解除綁定)
    initContextHolders(request, localeContext, requestAttributes);

    try {
        //抽象方法,交給DispatcherServlet方法實現
        doService(request, response);
    }
    catch (ServletException | IOException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (Throwable ex) {
        failureCause = ex;
        throw new NestedServletException("Request processing failed", ex);
    }

    finally {
        //重置LocaleContext和RequestAttributes對象,也就是解除LocaleContext對象和ServletRequestAttributes對象和當前請求線程的綁定
        resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }
        //發佈ServletRequestHandledEvent事件
        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}
//DispatcherServlet.java
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        attributesSnapshot = new HashMap<>();
        Enumeration<?> attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
            String attrName = (String) attrNames.nextElement();
            if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    }
    
    //在當前request對象中填充4個屬性
    request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
    request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
    request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

    if (this.flashMapManager != null) {
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
        }
        request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    }

    try {
        //主要處理分發請求
        doDispatch(request, response);
    }
    finally {
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (attributesSnapshot != null) {
                restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
    }
}


protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);
            
            //調用handlerMapping獲取handlerChain
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            //獲取支持該handler解析的HandlerAdapter
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            //使用HandlerAdapter完成handler處理
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            //視圖處理(頁面渲染)
            applyDefaultViewName(processedRequest, mv);
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }
        catch (Throwable err) {
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (Exception ex) {
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    catch (Throwable err) {
        triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));
    }
    finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        }
        else {
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}

        DispatcherServlet的doDispatch方法歸納起來大體就是如下幾點:首先根據當前請求路徑找到對應的HandlerMethod,一個HandlerMethod和若干個攔截器構造一個HandlerExecutionChain.經過HandlerExecutionChain獲得HandlerAdapter對象經過執行HandlerAdapter的handle方法獲得ModelAndView對象,調用ModelAndView解析視圖,渲染視圖,Response結束。

參考

http://www.javashuo.com/article/p-tdrvojaq-n.html
http://www.javashuo.com/article/p-tvgbymtf-bn.html
https://www.cnblogs.com/fangjian0423/p/springMVC-dispatcherServlet.html

相關文章
相關標籤/搜索