在Spring中, ContextLoaderListener只是輔助類,在web 容器啓動的時候查找並建立WebApplicationContext對象,經過該對象進行加載spring的配置文件。而真正的邏輯實現實際上是在DispatcherServlet中進行的,DispatcherServlet是實現servlet接口的實現類。web
DispatcherServlet 在 web.xml 中的配置以下:spring
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern><!-- 若是寫斜槓的話那就表示請求是否加後綴均可以 -->
</servlet-mapping>
DispatcherServlet 源碼解析
![](http://static.javashuo.com/static/loading.gif)
DispatcherServlet 的 init() 方法在 HttpServletBean() 中實現的app
init()
![](http://static.javashuo.com/static/loading.gif)
- 解析DispatcherServlet 配置的參數,封裝成 ServletConfigPropertyValues對象。
- 將當前Servlet 類型的實例轉換成BeanWrapper類型的實例。以便使用Spring中提供的注入功能進行對應的屬性注入。這些屬性如contextAttribute、contextClass、nameSpace、contextConfigLocation 等,均可以在web.xml 文件中以初始化參數的方式配置在servlet 的聲明中。
- 調用 initServletBean() 初始化servletBean。
onRefresh() 方法
在初始化servletBean的時候,最終會調用 onRefresh() 方法,該方法主要是刷新Spring在web功能實現中所必須使用的全局變量。post
![](http://static.javashuo.com/static/loading.gif)
- initMultipartResolver(context);
初始化文件上傳的處理類
- initLocaleResolver(context);
初始化國際化配置的處理類
- initThemeResolver(context);
初始化主題資源的處理類
- initHandlerMappings(context);
初始化處理請求的類,主要負責處理請求調用Controller的處理類。
- initHandlerAdapters(context);
初始化HandlerAdapter的適配器
- initHandlerExceptionResolvers(context);
初始化異常處理類。
- initRequestToViewNameTranslator(context);
初始化視圖轉換器,用於直接將請求轉換爲邏輯視圖名。
- initViewResolvers(context);
初始化視圖解析器,定義瞭如何經過view 名稱來解析對應View實例的行爲
- initFlashMapManager(context);
初始化Flash Map,提供一個請求存儲屬性,可供其它請求使用。
DispatchServlet的請求處理邏輯
servlet 接受到請求後,會調用service() 方法,而後service根據HTTP響應的請求方法進行調用響應的邏輯處理。url
![](http://static.javashuo.com/static/loading.gif)
從類結構中,能夠看出SpringMVC 支持 GET、POST、PUT、DELETE、OPTIONS、TRACE方法spa
![](http://static.javashuo.com/static/loading.gif)
從代碼中,咱們發現這幾個方法交給 processRequest() 來進行處理請求。3d
processRequest()->doService()->doDispatch()
經過跟蹤代碼,最終處理請求的核心代碼在doDispatch()方法中。code
doDispatch() 方法
![](http://static.javashuo.com/static/loading.gif)
- 檢查該請求是不是文件上傳請求,若是是則把request轉換爲 MultipartHttpServletRequest類型。
- 根據request信息查找對應的Handler,若是沒有找到對應的Handler,則經過response反饋錯誤信息。
- 經過當前的handler 查找對應的HandlerAdapter
- 判斷該HTTP請求是否是HEAD或GET請求,若是是則檢查HTTP請求頭部的LastModified屬性,來判斷該頁面是否須要從新加載。
![](http://static.javashuo.com/static/loading.gif)
- applyPreHandle() 執行該請求所匹配的攔截器,並調用全部匹配攔截器的preHandle()方法,進行處理
- 調用handle() 方法去根據請求路徑去調用用戶實現的Controller實現邏輯
- applyPostHandle()執行該請求全部匹配的攔截器,並調用全部匹配攔截器的postHandle()方法,進行處理
- processDispatchResult()處理頁面跳轉和調用攔截器的afterCompletion() 方法
processDispatchResult() 方法
![](http://static.javashuo.com/static/loading.gif)
- 處理異常信息
- 若是Controller成功返回了ModelAndView,則經過render()方法進行響應相應的頁面信息
- 執行完畢後,執行該請求全部匹配的攔截器,並調用全部匹配攔截器的afterCompletion()方法,進行處理