對于任何使用Spring Boot進行Web開發的開發者而言,深入理解Spring MVC的執行流程都是至關重要的。
這不僅有助于我們編寫更清晰、更高效的代碼,更是我們排查詭異問題、進行高級定制開發的知識基石。
今天,我們將一起深入Spring Boot應用的內核,揭開Spring MVC處理HTTP請求的神秘面紗。
一、核心設計:前端控制器模式
Spring MVC的核心架構基于前端控制器模式(Front Controller Pattern)。該模式的核心思想是:用一個中央控制器來統一接收所有請求,并將其分發給相應的處理組件 。
在Spring MVC中,這個中央控制器就是 DispatcherServlet
。它是由Spring Boot通過自動配置(WebMvcAutoConfiguration
)自動注冊的,默認映射路徑為 /
,這意味著它成為了你應用處理所有Web請求的單一入口 和總調度中心 。
整個流程可以概括為:請求 -> DispatcherServlet
-> 查找處理器 -> 執行處理器 -> 處理結果 -> 響應 。下面我們來分解這個過程的每一個細節。
二、詳細執行流程“八步走”
假設用戶發起了一個獲取用戶信息的請求:GET
http://localhost:8080/api/users/1
。
其處理流程如下圖所示,你可以結合下文步驟來理解:
第1步:請求抵達 DispatcherServlet
所有HTTP請求首先都會被 DispatcherServlet
接收。它是整個流程的“大腦”,負責協調后續的所有工作。
第2步:HandlerMapping
尋找處理器
DispatcherServlet
本身不處理業務邏輯,它的首要任務是問詢一個或多個 HandlerMapping
組件:“這個請求應該由誰來處理?”。
HandlerMapping
會根據請求的URL(如 /api/users/1
),在注冊的所有控制器中查找匹配的@RequestMapping
方法。找到后,它會返回一個 HandlerExecutionChain
對象。這個對象不僅包含了目標處理器(即我們@Controller
中的方法),還包含了配置好的攔截器(HandlerInterceptor
) 列表。
第3步:執行攔截器(Interceptor)的 preHandle
在真正執行業務邏輯之前,DispatcherServlet
會按順序執行 HandlerExecutionChain
中所有攔截器的 preHandle
方法。
攔截器在這里可以進行權限校驗、日志記錄、參數預處理等。如果某個攔截器認為請求不合法(如用戶未登錄),它的 preHandle
方法會返回 false
,從而直接中斷流程,跳轉到最后一步。
第4步:HandlerAdapter
適配并執行處理器
不同的處理器可能有不同的執行方式(例如普通的@Controller
和舊的Controller
接口)。DispatcherServlet
需要找到一個能“駕馭”當前處理器的 HandlerAdapter
。最常用的是 RequestMappingHandlerAdapter
。
HandlerAdapter
是真正的“執行指揮官”,它負責:
- 數據綁定:將請求參數、URL路徑變量、Session屬性等綁定到處理器方法的參數上。我們常用的
@RequestParam
、@PathVariable
、@RequestBody
等都是在這一步生效的。 - 數據驗證:如果參數標注了
@Valid
或@Validated
,會在此觸發校驗框架。 - 調用方法:最終通過反射機制,調用我們的控制器方法(如
UserController.getUserById(id)
),并獲取其返回值。
第5步:處理器處理業務并返回
我們的控制器方法開始執行業務邏輯(如調用Service層查詢用戶數據),然后返回一個結果。這個結果通常有兩種形式:
- 視圖名(String):例如返回
"userInfo"
,表示需要渲染一個視圖。 - 數據對象(Object):例如返回一個
User
對象,這在@RestController
中非常常見。
第6步:處理返回結果
這是流程的分水嶺,DispatcherServlet
會根據返回結果的類型選擇不同的處理策略:
- 返回視圖名?交給
ViewResolver
!
ViewResolver
(視圖解析器)會將邏輯視圖名(如"userInfo"
)解析為一個具體的View
對象(如對應/templates/userInfo.html
的ThymeleafView)。后續View
對象會負責將模型數據渲染到HTML模板中,生成最終頁面。
- 返回對象?交給
HttpMessageConverter
!
如果方法或類上有@ResponseBody
注解(@RestController
默認包含),DispatcherServlet
會遍歷配置的HttpMessageConverter
(消息轉換器)列表,選擇一個合適的轉換器(如MappingJackson2HttpMessageConverter
),將返回的Java對象序列化為JSON、XML等格式,并直接寫入HTTP響應體。
第7 & 8 步:攔截器收尾與響應返回
- 執行
postHandle
:控制器方法執行后(但在視圖渲染前 ),攔截器鏈會按逆序執行postHandle
方法,允許對模型數據進行最后修改。 - 執行
afterCompletion
:在整個請求處理完成(無論成功或異常)后,攔截器鏈會執行afterCompletion
方法,用于進行資源清理工作(如關閉連接)。 - 最終,生成的響應(HTML頁面或JSON數據)通過
DispatcherServlet
返回給客戶端瀏覽器。
三、不可或缺的異常處理機制
上述流程是“理想路徑”。如果任何步驟拋出異常,流程會立即中斷,并被 DispatcherServlet
捕獲。
此時,DispatcherServlet
會轉而委托 HandlerExceptionResolver
組件鏈來處理異常。這是我們實現統一異常處理的基礎:
ExceptionHandlerExceptionResolver
:支持我們使用@ControllerAdvice
和@ExceptionHandler
注解來全局處理異常。ResponseStatusExceptionResolver
:處理標注了@ResponseStatus
的異常。DefaultHandlerExceptionResolver
:處理Spring內置的一些標準異常(如405 Method Not Allowed)。
異常解析器會將異常轉換為一個友好的錯誤響應(如一個JSON錯誤信息),從而替代正常的流程結果。
總結
Spring MVC的流程清晰而模塊化,每個組件各司其職:
DispatcherServlet
是協調全局的大腦 。HandlerMapping
是負責尋路的地圖 。HandlerAdapter
是真正干活的雙手 。ViewResolver
&HttpMessageConverter
是包裝成果的化妝師 。HandlerInterceptor
是流程上的安檢員 。HandlerExceptionResolver
是兜底的消防員 。
Spring Boot的自動配置魔法讓我們無需手動組裝這些零件,但理解它們如何協同工作,無疑會讓你從一個Spring Boot的使用者,蛻變成為一個真正的架構理解者。希望這篇剖析能幫助你更好地駕馭Spring Boot Web開發。