Spring MVC 原理探祕-一個請求的旅行過程

【每日條語】當你停下腳步的時候,不要忘了別人還在奔跑。不怕萬人阻擋在前方,只怕自己先行投降。

最近個大長,中廠開始人才盤點,人才升級啦,經濟不景氣最後還是反應互聯網上來了,今天跟大家分享一個“一個請求的旅行過程”,可能面試的時候經常問,關注我的人可能最近也在找工作,與大家一起分享一下吧!

1:一個請求的旅行過程

在探索更深層次的原理之前,我們先來了解一下 Spring MVC 是怎麼處理請求的。弄懂了這個流程後,才能更好的理解具體的源碼。這裡我把 Spring MVC 處理請求的流程圖畫了出來,一起看一下吧:

Spring MVC 原理探秘-一個請求的旅行過程

如上,每一個重要的步驟上面都有編號。我先來簡單分析一下上面的流程,然後再向大家介紹圖中出現的一些組件。我們從第一步開始,首先,用戶的瀏覽器發出了一個請求,這個請求經過互聯網到達了我們的服務器。Servlet 容器首先接待了這個請求,並將該請求委託給 DispatcherServlet 進行處理。接著 DispatcherServlet 將該請求傳給了處理器映射組件 HandlerMapping,並獲取到適合該請求的攔截器和處理器。在獲取到處理器後,DispatcherServlet 還不能直接調用處理器的邏輯,需要進行對處理器進行適配。處理器適配成功後,DispatcherServlet 通過處理器適配器 HandlerAdapter 調用處理器的邏輯,並獲取返回值 ModelAndView。之後,DispatcherServlet 需要根據 ModelAndView 解析視圖。解析視圖的工作由 ViewResolver 完成,若能解析成功,ViewResolver 會返回相應的視圖對象 View。在獲取到具體的 View 對象後,最後一步要做的事情就是由 View 渲染視圖,並將渲染結果返回給用戶。

以上就是 Spring MVC 處理請求的全過程,上面的流程進行了一定的簡化,比如攔截器的執行時機就沒說。不過這並不影響大家對主過程的理解。下來來簡單介紹一下圖中出現的一些組件:

Spring MVC 原理探秘-一個請求的旅行過程

從上面的流程中可以看出,Spring MVC 對各個組件的職責劃分的比較清晰。DispatcherServlet 負責協調,其他組件則各自做分內之事,互不干擾。經過這樣的職責劃分,代碼會便於維護。

2:追根溯源之 Servlet

向大家介紹一下 Servlet,為什麼要介紹 Servlet 呢?原因不難理解,Spring MVC 是基於 Servlet 實現的。所以要分析 Spring MVC,首先應追根溯源,弄懂 Servlet。Servlet 是 J2EE 規範之一,在遵守該規範的前提下,我們可將 Web 應用部署在 Servlet 容器下。這樣做的好處是什麼呢?我覺得可使開發者聚焦業務邏輯,而不用去關心 HTTP 協議方面的事情。

Spring MVC 原理探秘-一個請求的旅行過程

如果我們寫的 Web 應用不大,不誇張的說,項目中對 HTTP 提供支持的代碼會比業務代碼還要多,這豈不是得不償失。當然,在現實中,有現成的框架可用,並不需要自己造輪子。如果我們基於 Servlet 規範實現 Web 應用的話,HTTP 協議的處理過程就不需要我們參與了。這些工作交給 Servlet 容器就行了,我們只需要關心業務邏輯怎麼實現即可。

3:Servlet 與 ServletConfig

Spring MVC 原理探秘-一個請求的旅行過程

init 方法會在容器啟動時由容器調用,也可能會在 Servlet 第一次被使用時調用,調用時機取決 load-on-start 的配置。容器調用 init 方法時,會向其傳入一個 ServletConfig 參數。ServletConfig 是什麼呢?顧名思義,ServletConfig 是一個和 Servlet 配置相關的接口。舉個例子說明一下,我們在配置 Spring MVC 的 DispatcherServlet 時,會通過 ServletConfig 將配置文件的位置告知 DispatcherServlet。

Servlet 中的 service 方法用於處理請求。當然,一般情況下我們不會直接實現 Servlet 接口,通常是通過繼承 HttpServlet 抽象類編寫業務邏輯的。Servlet 中接口不多,也不難理解,這裡就不多說了。下面我們來看看 ServletConfig 接口定義,如下:

Spring MVC 原理探秘-一個請求的旅行過程

3:DispatcherServlet 族譜

DispatcherServlet 是 Spring MVC 的核心,一起看看繼承關係圖

Spring MVC 原理探秘-一個請求的旅行過程

3.1:EnvironmentCapable

EnvironmentCapable 僅包含一個方法定義 getEnvironment,通過該方法可以獲取到環境變量對象。我們可以將 EnvironmentCapable 和 EnvironmentAware 接口配合使用,比如下面的實例:

Spring MVC 原理探秘-一個請求的旅行過程

3.2:HttpServletBean

HttpServletBean 是 HttpServlet 抽象類的簡單拓展。HttpServletBean 覆寫了父類中的無參 init 方法,並在該方法中將 ServletConfig 裡的配置信息設置到子類對象中,比如 DispatcherServlet。

3.3: FrameworkServlet

FrameworkServlet 是 Spring Web 框架中的一個基礎類,該類會在初始化時創建一個容器。同時該類覆寫了 doGet、doPost 等方法,並將所有類型的請求委託給 doService 方法去處理。doService 是一個抽象方法,需要子類實現。

3.4: DispatcherServlet

DispatcherServlet 主要的職責相信大家都比較清楚了,即協調各個組件工作。除此之外,DispatcherServlet 還有一個重要的事情要做,即初始化各種組件,比如 HandlerMapping、HandlerAdapter 等。

好像基本跟大家講概念最後給大家貼一張認為比較簡單的圖:

Spring MVC 原理探秘-一個請求的旅行過程

4:小結

"冬天來了,春天還會遠嗎?"-雪萊

即使你處在寒冷的冬天,只要你心中有光,你就能聞到春天的氣息;

即使你被困境所困,只要你心中有光,頭頂的烏雲總會被它所穿透;

即使你被挫折和失敗打翻一百次,只要你心中有光,你同樣可以一百零一 次站起來。

把苦澀的微笑留給昨天,用不屈的毅力和信念贏得未來!

相信一切會好起來的!!!!


分享到:


相關文章: