1. 程式人生 > >Spring mvc DispatchServlet 實現機制

Spring mvc DispatchServlet 實現機制

在Spring中, ContextLoaderListener只是輔助類,在web 容器啟動的時候查詢並建立WebApplicationContext物件,通過該物件進行載入spring的配置檔案。而真正的邏輯實現其實是在DispatcherServlet中進行的,DispatcherServlet是實現servlet介面的實現類。

DispatcherServlet 在 web.xml 中的配置如下:

<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 原始碼解析

DispatcherServlet 的 init() 方法在 HttpServletBean() 中實現的

init()


1. 解析DispatcherServlet 配置的引數,封裝成 ServletConfigPropertyValues物件。
2. 將當前Servlet 型別的例項轉換成BeanWrapper型別的例項。以便使用Spring中提供的注入功能進行對應的屬性注入。這些屬性如contextAttribute、contextClass、nameSpace、contextConfigLocation 等,都可以在web.xml 檔案中以初始化引數的方式配置在servlet 的宣告中。
3. 呼叫 initServletBean() 初始化servletBean。

onRefresh() 方法

在初始化servletBean的時候,最終會呼叫 onRefresh() 方法,該方法主要是重新整理Spring在web功能實現中所必須使用的全域性變數。

  1. initMultipartResolver(context);
    初始化檔案上傳的處理類
  2. initLocaleResolver(context);
    初始化國際化配置的處理類
  3. initThemeResolver(context);
    初始化主題資源的處理類
  4. initHandlerMappings(context);
    初始化處理請求的類,主要負責處理請求呼叫Controller的處理類。
  5. initHandlerAdapters(context);
    初始化HandlerAdapter的介面卡
  6. initHandlerExceptionResolvers(context);
    初始化異常處理類。
  7. initRequestToViewNameTranslator(context);
    初始化檢視轉換器,用於直接將請求轉換為邏輯檢視名。
  8. initViewResolvers(context);
    初始化檢視解析器,定義瞭如何通過view 名稱來解析對應View例項的行為
  9. initFlashMapManager(context);
    初始化Flash Map,提供一個請求儲存屬性,可供其它請求使用。

DispatchServlet的請求處理邏輯

servlet 接受到請求後,會呼叫service() 方法,然後service根據HTTP響應的請求方法進行呼叫響應的邏輯處理。

從類結構中,可以看出SpringMVC 支援 GET、POST、PUT、DELETE、OPTIONS、TRACE方法


從程式碼中,我們發現這幾個方法交給 processRequest() 來進行處理請求。

processRequest()->doService()->doDispatch()
通過跟蹤程式碼,最終處理請求的核心程式碼在doDispatch()方法中。

doDispatch() 方法


1. 檢查該請求是否是檔案上傳請求,如果是則把request轉換為 MultipartHttpServletRequest型別。
2. 根據request資訊查詢對應的Handler,如果沒有找到對應的Handler,則通過response反饋錯誤資訊。
3. 通過當前的handler 查詢對應的HandlerAdapter
4. 判斷該HTTP請求是不是HEAD或GET請求,如果是則檢查HTTP請求頭部的LastModified屬性,來判斷該頁面是否需要重新載入。


1. applyPreHandle() 執行該請求所匹配的攔截器,並呼叫所有匹配攔截器的preHandle()方法,進行處理
2. 呼叫handle() 方法去根據請求路徑去呼叫使用者實現的Controller實現邏輯
3. applyPostHandle()執行該請求所有匹配的攔截器,並呼叫所有匹配攔截器的postHandle()方法,進行處理
4. processDispatchResult()處理頁面跳轉和呼叫攔截器的afterCompletion() 方法

processDispatchResult() 方法


1. 處理異常資訊
2. 如果Controller成功返回了ModelAndView,則通過render()方法進行響應相應的頁面資訊
3. 執行完畢後,執行該請求所有匹配的攔截器,並呼叫所有匹配攔截器的afterCompletion()方法,進行處理

想了解更多精彩內容請關注我的公眾號