首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC 核心:HandlerMapping 與 HandlerAdapter 協作機制深度解析

     編輯:Java 綜合教學

Spring MVC 請求處理流程:HandlerMapping 與 HandlerAdapter 關係圖譜

許多開發者熟悉 @RequestMapping 與 HandlerInterceptor,但對 HandlerMapping 與 HandlerAdapter 的核心協作關係理解不深。本文從 DispatcherServlet 初始化與 doDispatch 流程切入,結合原始碼與時序圖,徹底釐清兩者職責與互動細節。

一、Spring MVC 雙容器架構

  • Root ApplicationContext(applicationContext.xml):載入 Service、DAO、DataSource、Redis 等非 Web 組件。
  • Servlet ApplicationContext(mvc-dispatcher-servlet.xml):載入 Controller、ViewResolver、HandlerMapping/Adapter 等 Web 組件。

雙容器關係圖

二、DispatcherServlet 初始化關鍵步驟

@Override
protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
}

protected void initStrategies(ApplicationContext context) {
    initHandlerMappings(context);   // 載入所有 HandlerMapping
    initHandlerAdapters(context);   // 載入所有 HandlerAdapter
    // ... 其他策略
}

HandlerMapping 初始化

透過 BeanFactoryUtils.beansOfTypeIncludingAncestors 掃描容器中所有 HandlerMapping 實現,重點為 RequestMappingHandlerMapping,它會掃描所有 @RequestMapping 註解,建立 mappingRegistry(URL → HandlerMethod 映射表)。

mappingRegistry 結構

HandlerAdapter 初始化

同樣掃描容器中所有 HandlerAdapter 實現,預設包含 RequestMappingHandlerAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter。RequestMappingHandlerAdapter 內部持有:

  • argumentResolvers:方法參數解析器(@PathVariable、@RequestParam、@RequestBody 等)
  • returnValueHandlers:返回值處理器
  • messageConverters:訊息轉換器(JSON/XML/表單)

HandlerAdapter 內部結構

三、請求處理核心流程 doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
    // 1. 獲取 Handler(Controller 方法封裝)
    mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null) { noHandlerFound(...); return; }

    // 2. 根據 Handler 類型獲取對應的 HandlerAdapter
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

    // 3. 委派 Adapter 執行真實 Handler,得到 ModelAndView
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    // ... 後續視圖渲染
}

時序圖簡述

  1. getHandler:遍歷 handlerMappings,匹配 URL → 返回 HandlerExecutionChain(含 Handler 與攔截器鏈)。
  2. getHandlerAdapter:遍歷 handlerAdapters,找到 supports(handler) 為 true 的 Adapter。
  3. ha.handle(...):Adapter 執行攔截器 preHandle → 調用 Handler 方法(參數解析、型別轉換) → 執行 postHandle → 返回 ModelAndView。

請求處理時序圖

四、核心差異與協作總結

維度HandlerMappingHandlerAdapter
職責「找人」:根據請求 URL 找到對應的 Handler(Controller 方法)「用人」:知道如何調用該 Handler(參數綁定、返回值處理、異常處理)
核心方法getHandler(request)handle(request, response, handler)
關鍵實現RequestMappingHandlerMappingRequestMappingHandlerAdapter
註冊資訊URL → HandlerMethod 映射表參數解析器、返回值處理器、訊息轉換器
擴展點自定義 URL 匹配規則自定義參數/返回值/轉換邏輯

五、實戰啟示

  • 自定義 HandlerMapping 可實現動態路由、多租戶 URL 隔離。
  • 自定義 HandlerAdapter 可支援非標準 Controller 介面(如函數式處理器)。
  • 理解兩者分工,排查「404 無映射」與「405 方法不支援/參數綁定失敗」更有的放矢。
參考:Spring MVC HandlerMapping 與 HandlerAdapter 詳細分析
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved