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

Spring MVC 框架核心源碼深度解析:DispatcherServlet 請求處理全流程

     編輯:Java 相關知識

架構概覽:DispatcherServlet 為核心的 MVC 執行引擎

Spring Web MVC 採用經典的 前端控制器模式,DispatcherServlet 作為唯一入口,協調 HandlerMapping、HandlerAdapter、HandlerExceptionResolver、ViewResolver 等核心組件完成請求分發、執行、異常處理、視圖渲染全流程。

初始化階段:九大組件的有序裝配

initFrameworkServlet() 按依賴順序初始化:

protected void initFrameworkServlet() {
    initMultipartResolver();      // 1. 文件上傳解析
    initLocaleResolver();         // 2. 國際化解析
    initThemeResolver();          // 3. 主題解析
    initHandlerMappings();        // 4. 處理器映射【核心】
    initHandlerAdapters();        // 5. 處理器適配器【核心】
    initHandlerExceptionResolvers(); // 6. 異常解析器
    initRequestToViewNameTranslator(); // 7. 請求到視圖名轉換
    initViewResolvers();          // 8. 視圖解析器【核心】
}

每個 initXxx() 均採用 「上下文查找 → 排序 → 緩存 → 無則用默認策略」 模式,體現了 Spring「約定優於配置」的設計哲學。

HandlerMapping:請求到執行鏈的映射中樞

接口契約

public interface HandlerMapping {
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

返回 HandlerExecutionChain,封裝 handler(Controller/HandlerMethod)+ interceptors[]。

SimpleUrlHandlerMapping 映射註冊與查找

  • 註冊階段(IOC 初始化時):解析 urlMap,調用 registerHandler(url, handler) 存入 handlerMap (HashMap)。支援 Bean 名稱懶加載與默認處理器 /*。
  • 查找階段:
    1. 精確匹配 handlerMap.get(lookupPath)。
    2. 模式匹配:遍歷 Key,用 AntPathMatcher 匹配,選最長路徑優先(bestPathMatch.length() <= registeredPath.length())。
    3. 回退默認處理器。

DispatcherServlet 請求處理主流程:doDispatch()

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
    HandlerExecutionChain mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null) { noHandlerFound(...); return; }
    
    // 1. 攔截器預處理(正序)
    for (HandlerInterceptor interceptor : mappedHandler.getInterceptors()) {
        if (!interceptor.preHandle(request, response, handler)) { 
            triggerAfterCompletion(...); return; 
        }
    }
    
    // 2. HandlerAdapter 執行業務邏輯
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());
    
    // 3. 攔截器後處理(逆序)
    for (int i = interceptors.length - 1; i >= 0; i--) {
        interceptors[i].postHandle(request, response, handler, mv);
    }
    
    // 4. 視圖渲染
    if (mv != null && !mv.wasCleared()) {
        render(mv, request, response);
    }
}

關鍵設計亮點

  • HandlerAdapter 適配器模式:SimpleControllerHandlerAdapter 適配 Controller 接口,RequestMappingHandlerAdapter 適配 @RequestMapping 方法,新協議只需新增 Adapter,DispatcherServlet 零修改。
  • 攔截器雙向鏈:preHandle 正序、postHandle 逆序、afterCompletion 逆序(保證資源釋放順序正確)。
  • ModelAndView 為契約:Handler 返回邏輯視圖名 + 模型數據,與具體視圖技術解耦。

視圖解析與渲染:ViewResolver + View 雙層抽象

視圖名解析鏈

protected View resolveViewName(String viewName, Locale locale) {
    for (ViewResolver vr : viewResolvers) {
        View view = vr.resolveViewName(viewName, locale);
        if (view != null) return view; // 首個非空即返回
    }
    return null;
}

支援多 ViewResolver 鏈,順序由 order 屬性決定。

InternalResourceView 渲染流程(JSP/模板引擎通用)

  1. render() → 合併靜態屬性 + 動態模型 → mergedModel。
  2. exposeModelAsRequestAttributes():將模型數據 request.setAttribute(),JSP/Thymeleaf 可直接取用。
  3. exposeHelpers():JSTL 區域化上下文等輔助對象。
  4. prepareForRendering() → getUrl()(由 UrlBasedViewResolver 構建:prefix + viewName + suffix)。
  5. RequestDispatcher.forward() 轉發到目標資源(JSP/模板文件)。

直接輸出類視圖

如 AbstractExcelView、AbstractPdfView、MappingJackson2JsonView 繼承 AbstractView,重寫 renderMergedOutputModel() 直接寫 HttpServletResponse.getOutputStream(),無需轉發。

核心組件協作時序圖(文本版)

Client Request
    ↓
DispatcherServlet.doService()
    ↓
DispatcherServlet.doDispatch()
    ↓
HandlerMapping.getHandler() → HandlerExecutionChain(handler + interceptors)
    ↓
Interceptor.preHandle() [正序]
    ↓
HandlerAdapter.handle() → ModelAndView
    ↓
Interceptor.postHandle() [逆序]
    ↓
ViewResolver.resolveViewName() → View
    ↓
View.render() → exposeModel → forward / write response
    ↓
Interceptor.afterCompletion() [逆序]
    ↓
Client Response

擴展點總結:如何優雅地定制 Spring MVC

擴展點接口/抽象類典型應用場景
請求映射HandlerMappingRESTful URL、版本號路由、動態權限映射
Handler 執行HandlerAdapter自定義參數綁定、返回值處理、異步處理
攔截邏輯HandlerInterceptor日誌、權限、限流、鏈路追蹤
異常處理HandlerExceptionResolver統一錯誤碼、友好錯誤頁、API 異常封裝
視圖解析ViewResolver多視圖技術共存、內容協商
視圖渲染ViewPDF/Excel/報表生成、自定義模板引擎

總結

Spring MVC 的優雅在於:將 Web 層的各種變化點(映射策略、執行協議、視圖技術、異常處理)全部抽象為可插拔的 Strategy 接口,DispatcherServlet 作為不變的協調者串聯起所有策略。這不僅實現了高度解耦,更為框架演進(如 WebFlux 的異步非阻塞模型)預留了架構空間。深入理解這套機制,能讓你在遇到「請求進不了 Controller」、「視圖解析失敗」、「攔截器不生效」等疑難雜症時,精準定位到具備組件與生命週期節點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved