所有的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請求的流程了: