转载

6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程

所有的http请求都会交给DispatcherServlet类的doDispatch方法进行处理,将DispatcherServlet.doDispatch函数的javadoc复制到下面:

/*      * Process the actual dispatching to the handler.      *       * The handler will be obtained by applying the servlet's HandlerMappings in      * order.The HandlerAdapter will be obtained by querying the servlet's      * installed HandlerAdapters to find the first that supports the handler      * class.      *       * All HTTP methods are handled by this method. It's up to HandlerAdapters      * or handlers themselves to decide which methods are acceptable.      */      void org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception;

下面分析doDispatch方法的流程,采用注释源码的方式:

1 protected void doDispatch(HttpServletRequest request,   2             HttpServletResponse response) throws Exception {   3            4         // processedRequest是经过checkMultipart方法处理过的request请求   5         HttpServletRequest processedRequest = request;   6         /**   7          * Handler execution chain, consisting of handler object and any handler   8          * interceptors. Returned by HandlerMapping's HandlerMapping.getHandler   9          * method. 看看HandlerExecutionChain类的属性就很清楚了:  10          *   11           public class HandlerExecutionChain {  12            13                   private final Object handler; //这个就是和该请求对应的handler处理方法  14            15                  //里面记录了所有的(any handler interceptors)和该请求相关的拦截器  16                   private HandlerInterceptor[] interceptors;  17             18                   private List<HandlerInterceptor> interceptorList;   19            20                   private int interceptorIndex = -1;   21                         22                   //...   23           }  24          *   25          */  26         HandlerExecutionChain mappedHandler = null;  27         boolean multipartRequestParsed = false;  28   29         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  30   31         try {  32             ModelAndView mv = null;  33             Exception dispatchException = null;  34   35             try {  36                 processedRequest = checkMultipart(request);  37                 multipartRequestParsed = (processedRequest != request);  38   39                 // Determine handler for the current request.Return a handler  40                 // and any interceptors for this request.  41                 /*  42                  * 得到的mappedHandler包含一个请求的handler处理方法以及与该请求相关的所有拦截器  43                  *   44                  * DispatcherServlet.getHandler方法会在底层调用HandlerMapping.getHandler方法  45                  * ,这个方法中会遍 历DispatcherServlet中的private List<HandlerMapping>  46                  * handlerMappings链表,找到能够处理当前 request请求的第一个HandlerMapping实例并返回:  47                  *   48                   protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  49                       for (HandlerMapping hm : this.handlerMappings) {  50                               HandlerExecutionChain handler = hm.getHandler(request);  51                               if (handler != null) {  52                                      return handler;  53                               }  54                       }  55                       return null;  56                   }  57                  *  58                  */  59                 mappedHandler = getHandler(processedRequest);  60                 // 如果没有找到和该请求相对应的mappedHandler,那么就会直接返回,并应答noHandlerFound异常  61                 if (mappedHandler == null || mappedHandler.getHandler() == null) {  62                     noHandlerFound(processedRequest, response);  63                     return;  64                 }  65   66                 // Determine handler adapter for the current request.  67                 /*  68                  * HandlerAdapter: 它是一个接口public interface HandlerAdapter  69                  * 看看源码上的说明:The DispatcherServlet accesses all installed  70                  * handlers through this interface, meaning that it does not  71                  * contain code specific to any handler type.  72                  *   73                  * 从后面的源码看出,在使用@RequestMapping注解标注handler方法的时候,获取到的是HandlerAdapter的  74                  * RequestMappingHandlerAdapter实现类的一个对象。  75                  *   76                  * 可以看看DispatcherServlet.getHandlerAdapter方法的定义,这个对理解上回很有帮助,我们会发现  77                  * ,getHandlerAdapter 方法和上面提到的getHandler方法一样都是寻找第一个可用的作为返回结果:  78                  *  79                  *   80                   protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {  81                      //this.handlerAdapters的定义是 private List<HandlerAdapter> handlerAdapters  82                          for (HandlerAdapter ha : this.handlerAdapters) {   83                               if (ha.supports(handler)) {  84                                    return ha;  85                               }  86                          }  87                          throw new ServletException("No adapter for handler [" + handler +  88                                  "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");  89                   }  90                  *   91                  */  92                 HandlerAdapter ha = getHandlerAdapter(mappedHandler  93                         .getHandler());  94   95                 // Process last-modified header, if supported by the handler.  96                 String method = request.getMethod();  97                 boolean isGet = "GET".equals(method);  98                 if (isGet || "HEAD".equals(method)) {  99                     long lastModified = ha.getLastModified(request, 100                             mappedHandler.getHandler()); 101                     if (logger.isDebugEnabled()) { 102                         logger.debug("Last-Modified value for [" 103                                 + getRequestUri(request) + "] is: " 104                                 + lastModified); 105                     } 106                     if (new ServletWebRequest(request, response) 107                             .checkNotModified(lastModified) && isGet) { 108                         return; 109                     } 110                 } 111  112                 // Apply preHandle methods of registered interceptors. 113                 /* 114                  * 会调用所有注册拦截器的preHandle方法,如果preHandle方法的返回结果为true,则会继续执行下面的程序, 115                  * 否则会直接返回。 116                  *  117                  * 分析一下HandlerExecutionChain.applyPreHandle方法的源码 : 118                   boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { 119                          //从上面的HandlerExecutionChain定义处可以看见有个interceptors,还有一个interceptorList。不知道有什么区别??! 120                          HandlerInterceptor[] interceptors = getInterceptors(); 121                          //如果已经注册有拦截器,则遍历拦截器 122                          if (!ObjectUtils.isEmpty(interceptors)) { 123                              for (int i = 0; i < interceptors.length; i++) { 124                                  HandlerInterceptor interceptor = interceptors[i]; 125                                  //如果注册拦截器的preHandle方法返回一个false,则该applyPreHandle方法就会返回false,从而在doDispatcher中的代码就不会往下执行了 126                                  if (!interceptor.preHandle(request, response, this.handler)) { 127                                       128                                      //这个方法要注意,它会调用所有已经成功执行的拦截器的afterCompletion方法,而且是反序调用的过程,可以分析triggerAfterCompletion 129                                      //的源代码,主要是利用interceptorIndex反减的方式实现的。下面是源码的英文注释: 130                                      //Trigger afterCompletion callbacks on the mapped HandlerInterceptors. 131                                       //Will just invoke afterCompletion for all interceptors whose preHandle invocation 132                                       //has successfully completed and returned true. 133                                      triggerAfterCompletion(request, response, null); 134                                      return false; 135                              } 136                                  //没成功执行一个拦截器的preHandle方法,其interceptorIndex就会增加1;原始值为-1。 137                                   this.interceptorIndex = i; 138                              } 139                          } 140                          return true; 141                      } 142                  * 143                  * 144                  *  顺带看看triggerAfterCompletion的源代码,很容易理解为什么拦截器的afterCompletion方法是反序执行的: 145                  *    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) 146                              throws Exception { 147                  148                         HandlerInterceptor[] interceptors = getInterceptors(); 149                         if (!ObjectUtils.isEmpty(interceptors)) { 150                             for (int i = this.interceptorIndex; i >= 0; i--) { 151                                 HandlerInterceptor interceptor = interceptors[i]; 152                                 try { 153                                     interceptor.afterCompletion(request, response, this.handler, ex); 154                                 } 155                                 catch (Throwable ex2) { 156                                     logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); 157                                 } 158                             } 159                         } 160                     } 161                  * 162                  * 163                  */ 164                 if (!mappedHandler.applyPreHandle(processedRequest, response)) { 165                     return; 166                 } 167  168                 // Actually invoke the handler. 169                 /* 170                  * 在这个函数里面会真正的执行request请求相对于的handler方法,可以想象:在真正调用方法之前还会有很多的 171                  * 先前处理。在这里仅仅是分析出大概的代码执行流程,其细节的部分在后面的单独模块源码分析的时候做详细的讲解。 172                  * 上面讲解到HandlerAdapter是一个接口:public interface HandlerAdapter,那么必然会有很多 173                  * 中实现类,在采用注解@RequstMapping的方式标注handler的情况下,ha.handle方法会在底层调用具体的 174                  * HandlerAdapter类实现方法RequestMappingHandlerAdapter.handleInternal 175                  *  176                  * 分析一下RequestMappingHandlerAdapter.handleInternal的源代码: 177                       protected ModelAndView handleInternal(HttpServletRequest request, 178                         HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { 179                         //好像是看control的类定义处是否使用了@SessionAttributes注解,checkAndPrepare方法有什么作用??? 180                         if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { 181                             // Always prevent caching in case of session attribute management. 182                             checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true); 183                         } 184                         else { 185                             // Uses configured default cacheSeconds setting. 186                             checkAndPrepare(request, response, true); 187                         } 188                          189                         // Execute invokeHandlerMethod in synchronized block if required. 190                         // 这里是个值得注意的地方,synchronizeOnSession的值默认为false,如果通过某个方法使得其为true,那么request对应的handler 191                         // 将会被放在同步快中进行处理。在什么时机下,使用什么方法才能将其设置为true呢??? 192                         if (this.synchronizeOnSession) { 193                             HttpSession session = request.getSession(false); 194                             if (session != null) { 195                                 Object mutex = WebUtils.getSessionMutex(session); 196                                 // 将handler放在同步块中处理 197                                 synchronized (mutex) { 198                                     return invokeHandleMethod(request, response, handlerMethod); 199                                 } 200                             } 201                         } 202                         //在invokeHandleMethod中会①将所有标注有@ModelAttrib的方法都执行一遍,②调用invokeAndHandle(webRequest, mavContainer) 203                         //方法,在这里面调用handler方法,③最后调用getModelAndView(mavContainer, modelFactory, webRequest)方法的到ModelAndView。 204                         //invokeHandleMethod这个方法还有很多东西要分析,留在后面。 205                         //从上面的③我们可以看出,无论handler采用哪种模型化处理方式,最后都是将结果转化为ModelAndView 206                         return invokeHandleMethod(request, response, handlerMethod); 207                     } 208                  */ 209                 mv = ha.handle(processedRequest, response, 210                         mappedHandler.getHandler()); 211  212                 if (asyncManager.isConcurrentHandlingStarted()) { 213                     return; 214                 } 215  216                 applyDefaultViewName(request, mv); 217                 /* 218                  * 调用request相关的拦截器的postHandle方法,注意,这个也是反序调用的。看看源代码: 219                  * 220                   void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { 221                         HandlerInterceptor[] interceptors = getInterceptors(); 222                         if (!ObjectUtils.isEmpty(interceptors)) { 223                             //注意,这里也是反序执行,而且是所有成功执行了的postHandle拦截器 224                             for (int i = interceptors.length - 1; i >= 0; i--) { 225                                 HandlerInterceptor interceptor = interceptors[i]; 226                                 //这里传入的参数中有mv,也就是说,我们是有办法在拦截器的postHandle方法中修改已经返回的mv 227                                 interceptor.postHandle(request, response, this.handler, mv); 228                             } 229                         } 230                     } 231                  */ 232                 mappedHandler.applyPostHandle(processedRequest, response, mv); 233             } catch (Exception ex) { 234                 dispatchException = ex; 235             } 236             processDispatchResult(processedRequest, response, mappedHandler, 237                     mv, dispatchException); 238         } catch (Exception ex) { 239             triggerAfterCompletion(processedRequest, response, mappedHandler, 240                     ex); 241         } catch (Error err) { 242             triggerAfterCompletionWithError(processedRequest, response, 243                     mappedHandler, err); 244         } finally { 245             if (asyncManager.isConcurrentHandlingStarted()) { 246                 // Instead of postHandle and afterCompletion 247                 if (mappedHandler != null) { 248                     mappedHandler.applyAfterConcurrentHandlingStarted( 249                             processedRequest, response); 250                 } 251             } else { 252                 // Clean up any resources used by a multipart request. 253                 if (multipartRequestParsed) { 254                     cleanupMultipart(processedRequest); 255                 } 256             } 257         } 258     }

看完源代码就可以总结出doDispath方法中处理http请求的流程了:

6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程

正文到此结束
Loading...