http請求從tomcat到springmvc的完整流程

語言: CN / TW / HK

在上一篇瞭解了springMVC是如何被tomcat載入並且整合spring之後,這次來研究一下一個請求是如何傳遞到我們的controller的.既然要研究請求流程,那麼這次從不同的角度來重新看一下 DispatcherServlet . 先來看一下繼承圖 image.png 我們知道一個請求到達tomcat之後會呼叫 servlet的service方法我們順著繼承類圖開始追蹤.

tomcat收到請求

為了能更徹底的瞭解整個原理,我們從tomcat接受到請求開始追蹤整個流程 1. tomcat監聽8080埠.首先是在NioEndPoint中的initServerSocket初始化服務端的監聽socket image.png 2. 收到客戶端跟服務端建立連線. tomcat啟動了一個 Acceptor執行緒監聽serversocket,如果有客戶端連線就把他丟到 selectorimage.png 3. poller執行緒非阻塞監聽selector,看客戶端有沒有發請求 image.png 4. 真正處理業務的是一個worker執行緒 image.png

流程圖

image.png tomcat的一些細節可以直接看我之前寫的tomcat原始碼分析,裡面比較詳細

DispatcherServlet 執行流程

我們首先來看一下dispatcherServlet的方法繼承 image.png doService方法中其實就是存了一些資料到request域中,然後呼叫了doDispatch方法 image.png

9大元件

在瞭解流程之前先看一下SpringMVC的幾個重要的元件 1. MultipartResolver 檔案上傳處理器 2. LocalResolver 國際化解析器 3. ThemeResolver 主題解析器 4. HandlerMapping 處理器對映: 儲存就是所有請求和controller的對映 5. HandlerAdapter 處理器的介面卡 6. HandlerExceptionResolver handler的異常解析器 7. RequestToViewNameTranslator 請求轉換為檢視的翻譯器 8. FlashMapManager 快閃記憶體管理器 9. ViewResolver 檢視解析器 這幾大元件在initStrategies方法中進行初始化

image.png

在初始化的過程中,只有MultipartResolver檔案上傳處理器沒有預設實現,其他的SpringMVC都會給預設實現 image.png 預設實現的邏輯都差不多,獲取一個策略類

image.png 策略類的生成其實就是去DispatcherServlet的類路徑下尋找DispatcherServlet.properties檔案 image.png 配置檔案中配置了不同的策略類

image.png

doDispatch

瞭解了SpringMVC的元件之後我們正式來看流程

image.png

檢查檔案上傳

image.png

getHandler

獲得一個handler,handler我們在配置檔案中已經看到了Handler預設有三個實現 image.png 其中最常用的HandlerMapping是RequestMappingHandlerMapping,是用@RequestMapping註解作為url路徑對映的。 而另一個RouterFunctionMapping是支援函式式webflux程式設計的處理器

image.png 我們可以看到在RequestMappingHandlerMapping 中已經儲存了請求和處理器的對映,那麼我們就來看看這個對映是如何被儲存進去的

SpringMVC儲存請求和controller對映流程

RequestMappingHandlerMapping實現了spring的生命週期函式,在初始化結束之後會呼叫鉤子方法

image.png 遍歷每個bean然後去看有沒有註解

image.png 如果有註解的話就會繼續執行 image.png 我們先來看遍歷controller的方法 image.png 方法就是遍歷controller中的每一個方法,然後判斷是否有結果,有就加到map裡面返回,判斷邏輯交給外部實現 image.png 獲得完controller的方法之後就是遍歷方法註冊進去即可 image.png

getHandlerAdapter 獲得handler的介面卡

我們在上面已經知道了handler的註冊和獲取邏輯,那麼只要反射呼叫這個handler就可以了,為什麼要一個adapter呢,我們來看SpringMVC做了什麼 image.png 獲得介面卡的邏輯很簡單,遍歷介面卡,哪個是介面卡可以適配這個handler就返回哪個介面卡。介面卡也定義在properties中

image.png 隨後呼叫攔截器鏈,如果有一個返回false則方法就不真正執行 image.png 執行每一個preHandle方法 image.png

TODO 執行目標方法

在獲得了介面卡之後正式開始執行目標方法,我們先來總覽方法