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); //檢查是否須要轉換成multipart處理 multipartRequestParsed = (processedRequest != request); //調整標識用於釋放資源 //(1)獲取對應的handler以及Interceptor攔截器鏈 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { //404處理 noHandlerFound(processedRequest, response); return; } //(2)根據給定的handler獲取支持的adpter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()) // Process last-modified header, if supported by the handler. //當請求方法爲Get時能夠根據lastModified進行頁面緩存 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //(3)執行攔截器鏈 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //(4)處理handler mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //是否註冊爲異步處理 if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); //(5)攔截器後處理 mappedHandler.applyPostHandle(processedRequest, response, mv); //異常處理 //(6)交給視圖解析器進行視圖處理 processDispatchResult(processedRequest, response, mappedHandler, mv,dispatchException); } finally { //返回前,處理異步請求 if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } //關閉文件上傳資源 else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
在這裏僅討論4.3.13版本的spring家族css
SimpleUrlHandlerMapping:以註冊鍵值對的方式映射路徑html
在使用springmvc時,有一個靜態文件映射處理的問題,也就是爲了讓spring將咱們的html、css、js等靜態資源放行須要配置一個指定路徑,默認爲 /** /webjar/**兩個,這兩個路徑就是存貯在SimpleUrlHandlerMapping中的,對應的則是咱們指定的路徑地址。java
BeanNameUrlHandlerMapping:經過註冊的beanname綁定URLweb
經過beanname綁定URL在形式上就相似於Struts2的映射方式,即一個類對應一個映射路徑,這麼作的好處呢,是能夠支持一部分方法 ,相似於lastmodified,須要實現接口,這就只能在SimpleUrlHandlerMapping和beannameUrlHandlerMapping上實現。spring
<bean name="/hello" class="com.demo.HelloController"/> <!-- 經過註冊的類名稱映射路徑 -->
RequestMappingHandlerMapping:經過@RequestMapping註解映射的路徑瀏覽器
經過註解映射也是咱們最經常使用的映射方式,這種映射路徑被存貯在該類中緩存
在執行getHandler(processedRequest);是以這樣的順序選擇的:併發
對註冊的全部Handler進行循環循環順序以下mvc
經過映射的匹配順序能夠發現,全部的靜態資源都是在類映射不成功的狀況下才會進行靜態資源查找。因此若是出現靜態資源名與類的URL映射路徑重名會出現沒法訪問靜態資源的狀況。app
例如:/hello 映射到hello()方法,則/hello.html 也會匹配到這個路徑上。(spring默認忽略擴展名)
獲取匹配映射路徑的對象
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { /*在經過對比request獲取對應的映射對象和攔截器對象, 並封裝到executionChain 執行鏈中返回*/ HandlerExecutionChain handler = hm.getHandler(request);//關鍵語句 } //略 return null; } protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } }
1. SimpleControllerHandlerAdapter
適配實現Controller接口的類
2.RequestMappingHandlerAdapter
用於處理@RequestMapping註解的
3HttpRequestHandlerAdapter
該對象處理返回時,不會生成modelAndview對象,用於響應靜態資源
RequestMappingHandlerAdapter
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter