源码深度解析SpringMvc请求运行机制(转) 源码深度解析SpringMvc请求运行机制

 
本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制。通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户端期间是怎么运转的。

1、用户请求处理过程:

1、用户发送请求时会先从DispathcherServler的doService方法开始,在该方法中会将ApplicationContext、localeResolver、themeResolver等对象添加到request中,紧接着就是调用doDispatch方法:

源码:

  1. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.     if (logger.isDebugEnabled()) {  
  3.         String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";  
  4.         logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +  
  5.                 " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");  
  6.     }  
  7.   
  8.     // Keep a snapshot of the request attributes in case of an include,  
  9.     // to be able to restore the original attributes after the include.  
  10.     Map<String, Object> attributesSnapshot = null;  
  11.     if (WebUtils.isIncludeRequest(request)) {  
  12.         attributesSnapshot = new HashMap<String, Object>();  
  13.         Enumeration<?> attrNames = request.getAttributeNames();  
  14.         while (attrNames.hasMoreElements()) {  
  15.             String attrName = (String) attrNames.nextElement();  
  16.             if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {  
  17.                 attributesSnapshot.put(attrName, request.getAttribute(attrName));  
  18.             }  
  19.         }  
  20.     }  
  21.   
  22.     // Make framework objects available to handlers and view objects.  
  23.       <strong>request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());  
  24.     request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);  
  25.     request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);  
  26.     request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());</strong>  
  27.   
  28.     FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);  
  29.     if (inputFlashMap != null) {  
  30.         request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));  
  31.     }  
  32.     request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());  
  33.     request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);  
  34.   
  35.     try {  
  36.         <strong>doDispatch(request, response);</strong>  
  37.     }  
  38.     finally {  
  39.         if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {  
  40.             return;  
  41.         }  
  42.         // Restore the original attribute snapshot, in case of an include.  
  43.         if (attributesSnapshot != null) {  
  44.             restoreAttributesAfterInclude(request, attributesSnapshot);  
  45.         }  
  46.     }  
  47. }  

doDispatch方法就是处理用户请求的方法。

2、进入该方法后首先会检查该请求是否是文件上传的请求(校验的规则是是否是post并且contenttType是否为multipart/为前缀)即调用的是checkMultipart方法;如果是的将request包装成MultipartHttpServletRequest。见源码:

doDispatch:

  1. processedRequest = checkMultipart(request);  
checkMultipart:
  1. protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {  
  2.         if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {  
  3.             if (request instanceof MultipartHttpServletRequest) {  
  4.                 logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +  
  5.                         "this typically results from an additional MultipartFilter in web.xml");  
  6.             }  
  7.             else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {  
  8.                 logger.debug("Multipart resolution failed for current request before - " +  
  9.                         "skipping re-resolution for undisturbed error rendering");  
  10.             }  
  11.             else {  
  12.                 return this.multipartResolver.resolveMultipart(request);  
  13.             }  
  14.         }  
  15.         // If not returned before: return original request.  
  16.         return request;  
  17.     }  
3、然后调用getHandler方法来匹配每个HandlerMapping对象,如果匹配成功会返回这个Handle的处理链HandlerExecutionChain对象,在获取该对象的内部其实也获取我们自定定义的拦截器,并执行了其中的方法

见源码:

doDispatch: 

  1. HandlerExecutionChain mappedHandler = null;  
  2. mappedHandler = getHandler(processedRequest);  
getHandler方法:
  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  
  2.         for (HandlerMapping hm : this.handlerMappings) {  
  3.             if (logger.isTraceEnabled()) {  
  4.                 logger.trace(  
  5.                         "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");  
  6.             }  
  7.             HandlerExecutionChain handler = hm.getHandler(request);  
  8.             if (handler != null) {  
  9.                 return handler;  
  10.             }  
  11.         }  
  12.         return null;  
  13.     }  
  1. hm.getHandler方法:  
  1. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  
  2.     Object handler = getHandlerInternal(request);  
  3.     if (handler == null) {  
  4.         handler = getDefaultHandler();  
  5.     }  
  6.     if (handler == null) {  
  7.         return null;  
  8.     }  
  9.     // Bean name or resolved handler?  
  10.     if (handler instanceof String) {  
  11.         String handlerName = (String) handler;  
  12.         handler = getApplicationContext().getBean(handlerName);  
  13.     }  
  14.     return getHandlerExecutionChain(handler, request);  
  15. }  
getHandlerExecutionChain:
  1. protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {  
  2.         HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?  
  3.                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));  
  4.         chain.addInterceptors(getAdaptedInterceptors());  
  5.   
  6.         String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);  
  7.         for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {  
  8.             if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {  
  9.                 chain.addInterceptor(mappedInterceptor.getInterceptor());  
  10.             }  
  11.         }  
  12.   
  13.         return chain;  
  14.     }  
4、执行拦截器的preHandle方法,如果返回false执行afterCompletion方法并理解返回

5、通过上述获取到了HandlerExecutionChain对象,通过该对象的getHandler()方法获得一个object通过HandlerAdapter进行封装得到HandlerAdapter对象

6、该对象调用handle方法来执行Controller中的方法,该对象如果返回一个ModelAndView给DispatcherServlet

7、DispatcherServlet借助ViewResolver完成逻辑试图名到真实视图对象的解析,得到View后DispatcherServlet使用这个View对ModelAndView中的模型数据进行视图渲染

本文转自:http://blog.csdn.net/liyantianmin/article/details/46948963