springMVC流程解析

一、springMVC流程分析

     1、一次请求的url流程

       springMVC流程解析

  •      (1)客户端发起的请求request通过核心处理器DispatcherServlet进行处理
  •      (2-3)核心处理器DispatcherServlet通过注册在spring中的HandlerMapping找到对应的Handler(其实是HandlerMethod,可以认为是我们编写的某个Controller对象的具体的某个方法 即通过映射器将请求映射到Controller的方法上),同时将注册在spring中的所有拦截器和Handler包装成执行链HandlerExecutionChain并返回给核心处理器DispatcherServlet
  •      (4)核心处理器DispatcherServlet 通过2-3部获取的Handler来查找对应的处理器适配器HandlerAdapter
  •       (5-7) 适配器调用实现对应接口的处理器,并将结果返回给适配器,结果中包含数据模型和视图对象,再由适配器返回给核心控制器
  •  (8-9)核心控制器将获取的数据和视图结合的对象传递给视图解析器,获取解析得到的结果,并由视图解析器响应给核心控制器
  •  (10)核心控制器将结果Response返回给客户端

二、springMVC源码解析

DisplaceServlet的初始化操纵请参考:https://blog.csdn.net/panyongcsd/article/details/52416279L

以下是针对DisplaceServlet初始化后进行的操作

1、springMVC的入口文件DispatcherServlet类 该类在web.xml中进行了配置

springMVC流程解析

2、doService()方法 每一次的http请求都会进行该方法中


    @Override

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

         //如果是debug状态 则打印调试相关日志

        if (logger.isDebugEnabled()) {

            String requestUri = urlPathHelper.getRequestUri(request);

            String resumed = WebAsyncUtils.getAsyncManager(request)
                     .hasConcurrentResult() ? " resumed" : "";

            logger.debug("DispatcherServlet with name '"
            + getServletName() + "'" + resumed +

            " processing " + request.getMethod() + 
            " request for [" + requestUri + "]");

        }

        // Keep a snapshot of the request attributes in case of an include,

        // to be able to restore the original attributes after the include.

        Map<String, Object> attributesSnapshot = null;

       //获取该DispatcherServlet中是否含有包含(include)的servlet

       //类似于<jsp:incluede page="xxx.jsp"/> 即在该jsp(servlet)中含有 xxx.jsp servlet

        if (WebUtils.isIncludeRequest(request)) {

            logger.debug("Taking snapshot of request attributes before include");

           //将请求中的所有参数放置到快照属性Map

            attributesSnapshot = new HashMap<String, Object>();

            Enumeration<?> attrNames = request.getAttributeNames();

            while (attrNames.hasMoreElements()) {

                String attrName = (String) attrNames.nextElement();

                if (this.cleanupAfterInclude || 
                        attrName.startsWith("org.springframework.web.servlet")) {

                    attributesSnapshot.put(attrName, request.getAttribute(attrName));

                }

            }

        }


       // Make framework objects available to handlers and view objects.

       //设置上下文环境

        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());、


        //从session中获取flashmap 属性 不为null的时候 将其添加到request

        //flashMap其实是为了重定向的时候隐式的出传递参数使用的

        //每次处理请求时,都会先判断一下FlashMap中是否有数据
        // 如果有就先设置到 inputFlashMap里面,也就是保存上次转发过来的属性 再设置到Model里面

        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块不知道执行什么操作,应该类似于资源的销毁等相关处理

        finally {

            if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

                return;

            }

// Restore the original attribute snapshot, in case of an include.

            if (attributesSnapshot != null) {

                restoreAttributesAfterInclude(request, attributesSnapshot);

            }

        }

}

3、doDispatch()方法

   该方法是springMVC核心流程操作的所涉及的最为关键的方法,主要执行流程也全部在该方法中进行体现。

/**
        真正处理转发请求的过程
        通过该servlet的注册的所有处理器映射器HandlerMapping中的进行url请求映射到具体的处理器Handler上 
        即通过HandlerMapping将具体的httpurl请求映射到Controller层对应 的方法上
        通过该servlet上注册的处理器适配器HandlerAdapter去查找第一个可以支持处理处理器Handler的HandlerAdapter
        通过查询所有的HTTP请求均被该方法处理,它是由HandlerApadaters和处理器解析类来决定该controller层的方法是合理的
     */
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
         //处理器执行链HandlerExecutionChain 里面包含handlerMethod和springMVC中所有的拦截器 
         //参考4HandlerExecutionChain类的介绍
        HandlerExecutionChain mappedHandler = null;
         //文件上传的处理请求标识
        boolean multipartRequestParsed = false;
         //将请求包装成异步请求来进行管理,为防止线程阻塞将请求的处理委托给另外一个线程
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
 
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;
 
            try {
               //检查当前request请求是否为文件上传请求,如果是将请求包装为文件上传请求返回,否则返回原请求
              //返回的请求和原来请求不一致,则multipartRequestParsed 标识为true
                processedRequest = checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
 
                   // Determine handler for the current request.
              //根据当前请求获取HandlerExecutionChain对象(核心关键 在下面进行详细叙述)
                mappedHandler = getHandler(processedRequest, false);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }
 
                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
 
                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
                    //执行所有拦截器的preHandler方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
 
                try {
                    // Actually invoke the handler.
                    //真正的执行我们编写的Controller的某个具体的方法,并返回视图和数据对象 
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                }
                finally {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
                }
 
                applyDefaultViewName(request, mv);
                //执行所有拦截器postHandler方法
                mappedHandler.applyPostHandle(processedRequest, response, mv); 
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Error err) {
            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion  执行拦截器的afterHandler方法
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                return;
            }
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }

4、HandlerExecutionChain 类

/**
处理器执行链 所有的http请求通过HandlerMapping都会返回该对象 其中包含handler处理器(Controller层要调用的方法)
还有spring注册的所有拦截器
*/

public class HandlerExecutionChain {
    private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);    
    //Controller层具体的某一个方法
    private final Object handler;
    //spring注册的所有拦截器
    private HandlerInterceptor[] interceptors;
    //spring注册的所有拦截器
    private List<HandlerInterceptor> interceptorList;
    //拦截器数组的游标
    private int interceptorIndex = -1;
     /**
     * Apply preHandle methods of registered interceptors.
     *执行拦截器的preHandle()方法
     */
    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (getInterceptors() != null) {
            for (int i = 0; i < getInterceptors().length; i++) {
                HandlerInterceptor interceptor = getInterceptors()[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    triggerAfterCompletion(request, response, null);
                    return false;
                }
                this.interceptorIndex = i;
            }
        }
       return true;
    }

/**
* Apply postHandle methods of registered interceptors.
* 执行拦截器的postHandle ()方法
*/
  void applyPostHandle(HttpServletRequest request, HttpServletResponse response,
        ModelAndView mv) throws Exception {
        if (getInterceptors() == null) {
            return;
        }
        for (int i = getInterceptors().length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = getInterceptors()[i];
            interceptor.postHandle(request, response, this.handler, mv);
        }
    }

    /**
      * 仅仅在拦截器的preHandle成功调用且返回true,才执行拦截器的afterCompletion ()方法
      * Will just invoke afterCompletion for all interceptors whose preHandle invocation
      * has successfully completed and returned true.
     */
    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
            throws Exception {
   if (getInterceptors() == null) {
           return;
       }
    for (int i = this.interceptorIndex; i >= 0; i--) {
         HandlerInterceptor interceptor = getInterceptors()[i];
            try {
                interceptor.afterCompletion(request, response, this.handler, ex);
            }
            catch (Throwable ex2) {
                logger.error("HandlerInterceptor.afterCompletion
                      threw exception", ex2);
        }
    }
  }
}    

5、获取HandlerExcutorChain对象的方法追踪

 5.1 dispatchServlet的getHandler

/**
     * Return the HandlerExecutionChain for this request.
      从请求中获取HandlerExecutionChain 。遍历该servlet中的所有HandlerMapping
    如果在遍历过程中找到对应的HandlerExecutionChain 就直接返回该对象
     */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {//遍历注册在spring中的HandlerMapping
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            } //通过HandlerMapping获取执行器链
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

5.2 HandlerMapping的getHandler()方法 

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
         //获取对应的HandlerMethod方法 参考5.3
        Object handler = getHandlerInternal(request);
        if (handler == null) {
                 //如果没有则获取默认的HandlerMethod方法
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // Bean name or resolved handler?
        //如果在xml中配置了bean,或者解析器的 即handler为string 
        if (handler instanceof String) {
            String handlerName = (String) handler;
                   //从spring的上下文环境中获取bean
            handler = getApplicationContext().getBean(handlerName);
        }
               //获取HandlerExecutionChain的执行链 添加拦截器和handler 参考5.4
        return getHandlerExecutionChain(handler, request);
    }

5.3 getHandlerInternal() 方法 查找指定的Controller中的请求方法

//根据请求url获取到具体的Conrtroller的方法   
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        //获取请求路径 例如: /front/productList.shtml
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        if (logger.isDebugEnabled()) {
            logger.debug("Looking up handler method for path " + lookupPath);
        }
        //通过请求url和请求信息 直接定位到对应Controller层的方法
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
 
        if (logger.isDebugEnabled()) {
            if (handlerMethod != null) {
                logger.debug("Returning handler method [" + handlerMethod + "]");
            }
            else {
                logger.debug("Did not find handler method for [" + lookupPath + "]");
            }
        }
        return (handlerMethod != null) ? handlerMethod.createWithResolvedBean() : null;
    }   

5.4 获取 HandlerExecutionChain链

//获取HandlerExecutionChain 链 //getHandlerExecutionChain  获取执行器链(该chain中包含请求对应的方法(HttpMethod)和所有的拦截器)
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        //handler(应该是HttpMethod) 为什么要进行这一步的操作?
	//创建执行链HandlerExecutionChain对象
        HandlerExecutionChain chain =
            (handler instanceof HandlerExecutionChain) ?
                (HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
        //添加拦截器到执行链条
        chain.addInterceptors(getAdaptedInterceptors());
 
        String lookupPath = urlPathHelper.getLookupPathForRequest(request);
	//MappedInterceptors来处理匹配路径的拦截器
		//如果当前路径与mappedInterceptor的要求url匹配 如果匹配则将其添加进去
        for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
            if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }
 
        return chain;
    }

6、对获取HandlerAdapter的追踪

//获取处理器适配器HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	//遍历用户初始化的所有适配器
	for (HandlerAdapter ha : this.handlerAdapters) {
    	if (logger.isTraceEnabled()) {
	    	logger.trace("Testing handler adapter [" + ha + "]");
		}
		//如果当前的handlerAdapter能够处理Handler则直接返回该处理器适配器
		if (ha.supports(handler)) {
			return ha;
		}
	}
	//否则抛出异常
	throw new ServletException("No adapter for handler [" + handler +
		"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

7、HandlerAdapter执行Handler返回ModelView视图

 7.1 AbstractHandlerMethodAdapter的handle方法

//HandlerAdapter调用handle方法  (该方法位于AbstractHandlerMethodAdapter中,具体的实现调用了HandlerInternal方法)
	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
        //该方法为抽像方法,具体交由子类去实现
		return handleInternal(request, response, (HandlerMethod) handler);
	}

7.2 执行子类的HandleInternal方法(以RequestMappingHandlerAdapter为例子)

 @Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        
		//checkAndPrepare方法的介绍 检查给于的请求request和响应response是否符合设置,
		//检查是否可以支持handlerMethod具体要执行的controller的方法),和必要的session并设置缓存时间
		
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			// Always prevent caching in case of session attribute management.
			checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
		}
		else {
			// Uses configured default cacheSeconds setting.
			checkAndPrepare(request, response, true);
		}

		//真正的执行处理invokeHandleMethod方法
		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return invokeHandleMethod(request, response, handlerMethod);
				}
			}
		}
               
		return invokeHandleMethod(request, response, handlerMethod);
	}

7.3 invokeHandleMethod

//执行invokeHandleMethod方法
	private ModelAndView invokeHandleMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);

		//创建数据类型转换工厂
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		//将handlerMethod方法来进行包装处理
		ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);

		//创建存放ModelAndView的容器
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		
		//RequestContextUtils.getInputFlashMap(request)可以获取到request中的attribute,
		// 并且将所有的request中的attribute放置在mavContainer中
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		
		//会将该HttpMethod对应的controller方法中的使用标记@ModelAttributes的方法都执行一遍
		modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
		
		mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

		//异步请求以及异步的一下处理(没有跟踪)
		AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
		asyncWebRequest.setTimeout(this.asyncRequestTimeout);

		final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.setTaskExecutor(this.taskExecutor);
		asyncManager.setAsyncWebRequest(asyncWebRequest);
		asyncManager.registerCallableInterceptors(this.callableInterceptors);
		asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

		if (asyncManager.hasConcurrentResult()) {
			Object result = asyncManager.getConcurrentResult();
			mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
			asyncManager.clearConcurrentResult();

			if (logger.isDebugEnabled()) {
				logger.debug("Found concurrent result value [" + result + "]");
			}
			requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
		}

		//执行(待续...)
		requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}
               //返回ModelAndView对象
		return getModelAndView(mavContainer, modelFactory, webRequest);
	}