Spring MVC 處理請求的流程
- 流程步驟詳解
- 第1步:發起請求 (HTTP Request)
- 第2步:映射處理器 (Handler Mapping)
- 第3步:獲取適配器 (Handler Adapter)
- 第4步:執行攔截器前置處理 (Interceptors - preHandle)
- 第5步:真正調用處理器 (Handler Execution)
- 第6步:執行攔截器后置處理 (Interceptors - postHandle)
- 第7步:處理分發結果 (Process Dispatch Result)
- 第8步:執行攔截器完成處理 (Interceptors - afterCompletion)
- 第9步:返回響應 (HTTP Response)
- 核心組件總結
Spring MVC 處理請求的流程是其最核心的機制,理解它對于掌握整個框架至關重要。這個過程圍繞一個核心——前端控制器模式(Front Controller Pattern),即 DispatcherServlet。
整個流程清晰且模塊化,下圖展示了從請求發起到響應返回的完整生命周期,以及其中涉及的核心組件交互:
流程步驟詳解
現在,我們結合上圖,對每一個步驟進行詳細解讀:
第1步:發起請求 (HTTP Request)
請求離開瀏覽器,到達 DispatcherServlet
。根據 web.xml 或 Servlet 3.0+ 的配置,所有匹配特定模式(如 /
)的請求都會由它處理。
第2步:映射處理器 (Handler Mapping)
DispatcherServlet
咨詢一個或多個 HandlerMapping
Bean:“這個請求應該由哪個‘處理器’(Handler)來處理?”。HandlerMapping
根據請求的 URL 進行查找。
- 常見實現:
RequestMappingHandlerMapping
:用于映射@RequestMapping
注解的方法(最常用)。BeanNameUrlHandlerMapping
:根據 Bean 的名字進行映射。
- 返回結果:不僅返回找到的目標處理器方法,還會返回一個
HandlerExecutionChain
對象,該對象包含了找到的 Handler 以及所有適用于該請求的HandlerInterceptor
(攔截器)。
第3步:獲取適配器 (Handler Adapter)
DispatcherServlet
拿著找到的 Handler,問一堆 HandlerAdapter
:“你們誰支持(support)這個 Handler 的類型?”
- 為什么需要它?:Handler 的類型五花八門(如
@Controller
、HttpRequestHandler
、Servlet
)。DispatcherServlet
需要一個統一的接口來調用它們。HandlerAdapter
是適配器模式的典型應用,它屏蔽了不同處理器的調用細節。 - 常見實現:
RequestMappingHandlerAdapter
(用于適配@RequestMapping
注解的方法)。
第4步:執行攔截器前置處理 (Interceptors - preHandle)
在真正調用業務邏輯之前,DispatcherServlet
會調用 HandlerExecutionChain
中所有攔截器的 preHandle()
方法。
- 應用:進行權限檢查、日志記錄、 locale 解析等。
第5步:真正調用處理器 (Handler Execution)
現在,DispatcherServlet
讓獲取到的 HandlerAdapter
去真正地執行 Handler。
這個執行過程非常復雜,包括:
- 參數解析:根據方法簽名,使用各種
HandlerMethodArgumentResolver
來解析方法的參數(如@RequestParam
,@RequestBody
,@PathVariable
)。 - 調用方法:通過反射調用控制器方法。
- 返回值處理:使用方法返回值,使用各種
HandlerMethodReturnValueHandler
處理返回值(如@ResponseBody
,ModelAndView
)。
第6步:執行攔截器后置處理 (Interceptors - postHandle)
控制器方法執行完畢后,DispatcherServlet
會逆序調用所有攔截器的 postHandle()
方法。
- 應用:有機會修改即將發送到視圖的
ModelAndView
對象。
第7步:處理分發結果 (Process Dispatch Result)
這是視圖渲染和響應的核心環節。DispatcherServlet
根據控制器方法的返回結果,進行不同的處理:
- 情況A:方法有
@ResponseBody
或返回ResponseEntity
- 流程:
RequestResponseBodyMethodProcessor
會使用配置的HttpMessageConverter
(如MappingJackson2HttpMessageConverter
)將返回值(如一個 Java 對象)直接序列化(如轉為 JSON),并寫入HttpServletResponse
的輸出流。此過程不涉及視圖解析。
- 流程:
- 情況B:方法返回視圖名(如 String)或
ModelAndView
- 視圖解析:
DispatcherServlet
調用ViewResolver
來根據邏輯視圖名(如"success"
)解析為一個具體的View
對象(如InternalResourceView
對應 JSP,ThymeleafView
對應 Thymeleaf)。 - 視圖渲染:
DispatcherServlet
將模型數據傳遞給View
對象,并調用其render()
方法。該方法會生成最終的 HTML 內容(如合并 JSP 模板和模型數據),并將其寫入HttpServletResponse
的輸出流。
- 視圖解析:
第8步:執行攔截器完成處理 (Interceptors - afterCompletion)
無論請求處理成功還是出現異常,DispatcherServlet
都會最終觸發所有攔截器的 afterCompletion()
方法。
- 應用:進行資源清理、記錄請求完成時間等。
第9步:返回響應 (HTTP Response)
最終,完整的響應通過 Servlet 容器(如 Tomcat)返回給客戶端。
核心組件總結
組件 | 職責 | 類比 |
---|---|---|
DispatcherServlet | 前端控制器,協調所有組件,是整個流程的總指揮。 | 餐廳的前臺經理 |
HandlerMapping | 請求映射,根據 URL 找到對應的處理器。 | 餐廳的引座員 |
HandlerAdapter | 處理器適配,用統一的接口調用各種不同類型的處理器。 | 餐廳的服務員,連接經理和后廚 |
Handler | 處理器(通常是我們寫的 @Controller )。 | 餐廳的廚師 |
ViewResolver | 視圖解析器,將邏輯視圖名解析為具體視圖對象。 | 餐廳的出菜員 |
View | 視圖,負責將模型數據渲染成最終的響應內容(HTML/JSON等)。 | 最終呈現的菜肴 |
HandlerInterceptor | 攔截器,在請求處理的不同階段進行橫切處理。 | 餐廳的質檢員 |
這個流程充分體現了 Spring MVC 的高度可配置性和可擴展性。其中的每一個步驟幾乎都可以通過配置自定義組件或實現特定接口來進行干預和擴展。