文章目錄
- 一、設計哲學:分層與解耦
- 1. 前端控制器模式
- 2. 分層架構設計
- 二、核心組件源碼解析
- 1. DispatcherServlet - 九大組件初始化
- 2. DispatcherServlet - 前端控制器(請求處理中樞)
- 請求源碼入口:FrameworkServlet#doGet()
- 請求委托分發:DispatcherServlet#doService()
- 核心請求處理:DispatcherServlet#doDispatch()
- 3. HandlerMapping - 請求映射處理器(請求路由引擎)
- 4. HandlerAdapter - 處理器適配器
- 5. HandlerMethodArgumentResolver - 參數解析器
- 6. HandlerMethodReturnValueHandler - 返回值處理器
- 7. RequestToViewNameTranslator - 視圖名轉換器
- 8. HandlerExceptionResolvers - 異常解析器
- 9. ViewResolver - 視圖解析器(渲染視圖)
- 10. LocaleResolver - 地區區域解析器(國際化i18n)
- 三、請求處理全流程剖析
- 關鍵流程說明:
- 四、核心設計模式應用
- 1. 策略模式(組件可插拔)
- 2. 模板方法模式(流程標準化)
- 3. 責任鏈模式(攔截器棧)
- 五、擴展機制實戰
- 1. 自定義參數解析器
- 2. 自定義視圖解析器
- 六、性能優化設計
- 1. 映射緩存機制
- 2. 快速失敗機制
- 3. 性能優化方案
- 七、Spring MVC 設計精髓總結
- 擴展
Spring MVC作為Java Web開發的標桿框架,其優雅的設計思想和可擴展架構值得我們深入探究。它是 Spring 框架的核心模塊,采用了經典的前端控制器模式,本文將結合核心源碼,揭示其內部工作機制。
關于Spring MVC上下文容器(DispatcherServlet
容器)的啟動-創建-初始化,可以參閱文章:【Spring MVC上下文容器在Web容器中是如何啟動的(源碼深入剖析)?】
一、設計哲學:分層與解耦
1. 前端控制器模式
Spring MVC 是 Spring 框架的核心模塊,Spring MVC采用了經典的前端控制器模式,通過高度組件化的設計實現職責分離和可擴展性:
核心設計原則:
- 單一職責:每個組件只負責特定功能
- 開閉原則:通過接口擴展而非修改
- 分層處理:請求處理流程清晰分層
DispatcherServlet
作為統一入口,接收所有 HTTP 請求;通過策略接口將請求處理職責分發給不同組件
2. 分層架構設計
- 控制層(Controller):處理請求,協調業務邏輯
- 業務層(Service):實現核心業務邏輯
- 數據層(DAO):處理數據持久化
- 視圖層(View):渲染響應結果
二、核心組件源碼解析
1. DispatcherServlet - 九大組件初始化
源碼路徑:org.springframework.web.servlet.DispatcherServlet
核心方法:initStrategies
初始化文件解析器:initMultipartResolver()
- 組件主要作用:文件上傳解析器的作用是將
multipart/form-data
類型的請求解析為普通的表單字段和文件字段,便于后續處理。 - 標準實現類:
StandardServletMultipartResolver
- 是
MultipartResolver
接口的標準實現 - 基于 Servlet 3.0 的
javax.servlet.http.Part API
- 需要在 web.xml 或通過編程方式配置 Servlet 的
"multipart-config"
- 是
- 核心功能源碼:
- 多部分請求檢測 - 通過
isMultipart()
方法檢查請求內容類型是否為"multipart/"
- 多部分請求解析 - 使用
resolveMultipart()
方法將普通請求轉換為MultipartHttpServletRequest
- 資源清理 - 通過 cleanupMultipart() 方法刪除上傳的臨時文件
- 多部分請求檢測 - 通過
初始化地區區域解析器(國際化i18n):initLocaleResolver()
- 組件主要作用:用于根據請求確定當前的區域設置(
Locale
)。它允許應用程序支持國際化和本地化功能,例如根據用戶的語言偏好顯示內容。,LocaleResolver
的默認實現是AcceptHeaderLocaleResolver
,它通過 HTTP 請求頭中的Accept-Language
來解析用戶的區域設置。 - 默認實現類:
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
- 實現了
LocaleResolver
接口 - 基于 HTTP 請求頭中的
"Accept-Language"
字段來確定客戶端的區域設置 - 這是 Spring MVC 默認的區域解析器
- 實現了
- 核心功能:
- 支持的區域列表: 可通過
setSupportedLocales()
方法配置支持的區域列表進行匹配 - 默認區域設置: 可通過
setDefaultLocale()
方法設置當請求中沒有Accept-Language
頭時的默認區域 - 智能匹配機制:
- 優先匹配完整的語言和國家/地區組合
- 當沒有完全匹配時,會嘗試匹配語言部分
- 按照請求中
Accept-Language
頭的優先級順序進行匹配
- 支持的區域列表: 可通過
初始化主題解析器:initThemeResolver()
- 組件主要作用:根據請求確定當前的主題(例如頁面的樣式或布局);默認的
FixedThemeResolver
會固定使用一個主題,無法動態切換。用處不大😂。 - 默認實現類:
org.springframework.web.servlet.theme.FixedThemeResolver
- 繼承自
AbstractThemeResolver
- 實現了
ThemeResolver
接口 - 提供固定的主題解析策略
- 繼承自
- 核心功能點:
- 固定主題返回 -
resolveThemeName()
方法總是返回同一個預設的主題名稱 - 不支持動態更改 -
setThemeName()
方法拋出UnsupportedOperationException
,因為主題是固定的無法更改
- 固定主題返回 -
初始化處理器映射器(路由映射):initHandlerMappings()
- 組件主要作用:負責建立 HTTP 請求與處理器(Handler)之間的映射關系。它的核心作用可概括為:根據請求信息(URL、請求方法、請求頭等)找到對應的處理器(Controller 方法)。
- 默認實現:
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
- 常用實現:
RequestMappingHandlerMapping
- 繼承自
RequestMappingInfoHandlerMapping
- 實現了
MatchableHandlerMapping
和EmbeddedValueResolverAware
接口 - Spring MVC 3.1 版本引入,是基于注解的請求映射核心組件
- 繼承自
- 核心初始化源碼:
-
請求映射創建 - 從帶有
@RequestMapping
注解的控制器類和方法創建RequestMappingInfo
實例
-
處理器檢測 - 通過
isHandler()
方法識別帶有@Controller
或@RequestMapping
注解的類
初始化處理器適配器(調用 Controller):initHandlerAdapters()
- 組件主要作用:
HandlerAdapter
是連接DispatcherServlet
與具體處理器(Handler)的關鍵組件,負責實際調用處理器方法并處理返回值。Spring MVC 提供了多種默認實現,支持不同類型的處理器。 - 默認實現:
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
- 常用實現:
RequestMappingHandlerAdapter
- 繼承自
AbstractHandlerMethodAdapter
- 實現了
BeanFactoryAware
和InitializingBean
接口 - Spring MVC 3.1 版本引入,是基于注解的請求處理核心組件
- 繼承自
- 核心初始化源碼:
初始化異常解析器:initHandlerExceptionResolvers
- 組件主要作用:
HandlerExceptionResolver
是處理控制器執行過程中拋出異常的核心組件。Spring 提供了多個默認實現,共同構成了異常處理的完整體系。 - 核心初始化源碼:
初始化視圖名轉換器:initRequestToViewNameTranslator()
- 組件主要作用:
RequestToViewNameTranslator
是一個關鍵的視圖解析輔助組件,它負責在控制器方法沒有顯式返回視圖名稱時,自動根據請求信息推導出默認的視圖名稱。 - 默認實現類:
org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
初始化視圖解析器(渲染視圖):initViewResolvers()
- 組件主要作用:
ViewResolver
是 Spring MVC 的關鍵組件,負責將控制器返回的邏輯視圖名稱解析為實際的視圖對象(View),以便后續渲染為最終輸出(如HTML頁面或JSON響應)? - 默認實現類:
org.springframework.web.servlet.view.InternalResourceViewResolver
- 核心初始化源碼:
初始化Flash 屬性管理器:initFlashMapManager()
- 組件主要作用:
FlashMapManager
是 Spring MVC 中用于在重定向場景下跨請求傳遞臨時參數的核心組件,其默認實現基于 Session 存儲,確保參數在重定向后自動傳遞且無需暴露在 URL 中。 - 默認實現類:
org.springframework.web.servlet.support.SessionFlashMapManager
2. DispatcherServlet - 前端控制器(請求處理中樞)
源碼路徑:org.springframework.web.servlet.DispatcherServlet
核心方法:doDispatch()
一次HTTP請求過程:
DispatcherServlet#doGet()/doPost()/..[FrameworkServlett#doGet()/doPost()/..]
- –>
FrameworkServlet#processRequest()
- –>
FrameworkServlet#doService()[DispatcherServlet#doService()]
- –>
DispatcherServlet#doDispatch()
請求源碼入口:FrameworkServlet#doGet()
請求委托分發:DispatcherServlet#doService()
核心請求處理:DispatcherServlet#doDispatch()
3. HandlerMapping - 請求映射處理器(請求路由引擎)
以常用的 HandlerMapping
實現類 RequestMappingHandlerMapping
進行分析。
源碼路徑:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
源碼解析:
DispatcherServlet.getHandler()
AbstractHandlerMapping.getHandler()
AbstractHandlerMethodMapping.getHandlerInternal()
AbstractHandlerMethodMapping.lookupHandlerMethod()
AbstractHandlerMethodMapping.addMatchingMappings()
RequestMappingInfoHandlerMapping.getMatchingMapping()
這里最終調用的是RequestMappingInfo#getMatchingCondition()
方法, 貌似看跟 RequestMappingHandlerMapping
沒啥關系,但是玄機就在于RequestMappingInfo
這個對象的來源:
- 它負責創建和配置
RequestMappingInfo
對象 - 它提供匹配所需的上下文配置(如是否支持后綴匹配等)
- 它決定了哪些類和方法應該被當作處理器處理(通過 isHandler() 方法)
- 它提供了創建映射信息的邏輯(通過 getMappingForMethod() 方法)
所以雖然直接調用的是 RequestMappingInfo
的方法,但 RequestMappingHandlerMapping
提供了匹配所需的配置和上下文,是整個機制不可缺少的一部分。
最后:這里最終會獲得一個HandlerMapping
對象,加之基于請求path配置的所有匹配的一個或多個HandlerInterceptor
對象一起包裝為HandlerExecutionChain
對象并返回。
4. HandlerAdapter - 處理器適配器
以常用的 HandlerAdapter
實現類 RequestMappingHandlerAdapter
進行分析。
源碼路徑:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
核心方法:handleInternal()
源碼解析:
AbstractHandlerMethodAdapter.supports()
RequestMappingHandlerAdapter.supportsInternal()
核心要點:最終這里會返回一個可以使用的HandlerAdapter
,即RequestMappingHandlerAdapter
;關于RequestMappingHandlerAdapter.supportsInternal()
總是返回true
這里在闡述下:
- 專用適配器:
RequestMappingHandlerAdapter
是專門為處理帶有@RequestMapping
注解的處理器方法而設計的,所以它支持所有HandlerMethod
實例。 - 前期篩選:在請求處理流程中,已經通過
RequestMappingHandlerMapping
確保了只有帶有@RequestMapping
注解的方法才會被路由到這個適配器。 - 靈活性:通過返回
true
,該適配器可以處理所有通過RequestMappingHandlerMapping
映射的處理器方法,無需額外的運行時檢查。
這個方法的設計體現了Spring MVC的職責分離原則:RequestMappingHandlerMapping
負責確定哪些方法可以處理請求,而 RequestMappingHandlerAdapter
負責實際執行這些方法。由于這兩個組件是成對工作的,所以適配器可以安全地接受所有由映射器提供的處理器方法。
在找到合適的HandlerAdapter
之后會先執行HandlerExecutionChain
的前置攔截器處理邏輯,源碼如下:
HandlerExecutionChain.applyPreHandle()
所有已注冊匹配的攔截器鏈上的前置攔截邏輯正常執行完畢之后緊接著才實際調用處理器核心處理方法(HandlerAdapter.handle()
),返回結果視圖對象,源碼如下:
AbstractHandlerMethodAdapter.handle()
RequestMappingHandlerAdapter.handleInternal()
RequestMappingHandlerAdapter.invokeHandlerMethod()
ServletInvocableHandlerMethod.invokeAndHandle()
核心要點:這里最后執行 invokeAndHandle()
方法是Spring MVC執行控制器方法
和處理返回值的關鍵環節,它通過策略模式使用不同的返回值處理器來處理各種類型的返回值,實現了高度靈活的返回值處理機制。
RequestMappingHandlerAdapter.getModelAndView()
核心要點:至此,執行完了 HandlerMethod
(處理 HTTP 請求),最后并返回 ModelAndView
對象(如果是通過 @ResponseBody
直接寫入響應,則返回null
)。
5. HandlerMethodArgumentResolver - 參數解析器
以常用的 HandlerMethodArgumentResolver
實現類 RequestResponseBodyMethodProcessor
進行分析。
源碼路徑:org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
核心方法:resolveArgument()
源碼解析:
InvocableHandlerMethod.getMethodArgumentValues()
HandlerMethodArgumentResolverComposite.supportsParameter()
HandlerMethodArgumentResolverComposite.getArgumentResolver()
RequestResponseBodyMethodProcessor.supportsParameter()
HandlerMethodArgumentResolverComposite.resolveArgument()
RequestResponseBodyMethodProcessor.resolveArgument()
核心要點:getMethodArgumentValues()
方法通過策略模式和組合模式,實現了靈活的參數解析機制,使得Spring MVC能夠處理各種類型的控制器方法參數,這是Spring MVC參數綁定功能的核心實現。
常見的參數解析器:
@PathVariable
->PathVariableMethodArgumentResolver
@RequestParam
->RequestParamMethodArgumentResolver
@RequestBody
->RequestResponseBodyMethodProcessor
@RequestHeader
->RequestHeaderMethodArgumentResolver
6. HandlerMethodReturnValueHandler - 返回值處理器
以常用的 HandlerMethodReturnValueHandler
實現類 RequestResponseBodyMethodProcessor
進行分析。
源碼路徑:org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
核心方法:handleReturnValue()
源碼解析:
HandlerMethodReturnValueHandlerComposite.selectHandler()
RequestResponseBodyMethodProcessor.supportsReturnType()
RequestResponseBodyMethodProcessor.handleReturnValue()
核心要點:handleReturnValue()
方法是實現RESTful API的關鍵組件,它使Spring MVC能夠直接將Java對象序列化為HTTP響應體,支持多種數據格式(JSON、XML等),是現代Web開發中處理API響應的核心機制。
7. RequestToViewNameTranslator - 視圖名轉換器
以常用的 RequestToViewNameTranslator
實現類 DefaultRequestToViewNameTranslator
進行分析。
源碼路徑:org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
核心方法:getViewName()
源碼解析:
DispatcherServlet.getDefaultViewName()
DefaultRequestToViewNameTranslator.getViewName()
核心要點:getViewName()
是 DefaultRequestToViewNameTranslator 類的核心方法,,該方法提供了一種約定優于配置的方式,根據HTTP請求URL自動生成合適的視圖名稱。
方法執行到這里其主要的邏輯已經執行完畢了, 有了完整的返回結果, 這時會執行攔截器的后置處理方法(applyPreHandle()
), 攔截器來源于前面匹配的 HandlerExecutionChain
,其源碼如下:
HandlerExecutionChain.applyPostHandle()
接下就是最終環節了, 處理結果(渲染視圖/處理異常)等, 接著往下看源碼:
DispatcherServlet.processDispatchResult()
8. HandlerExceptionResolvers - 異常解析器
以常用的 HandlerExceptionResolvers
實現類 ExceptionHandlerExceptionResolver
進行分析。
源碼路徑:org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
核心方法:doResolveHandlerMethodException()
源碼解析:
HandlerExceptionResolverComposite.resolveException()
AbstractHandlerExceptionResolver.resolveException()
AbstractHandlerMethodExceptionResolver.doResolveException()
ExceptionHandlerExceptionResolver.doResolveHandlerMethodException()
核心要點:這里正常情況下我們通過 ExceptionHandlerExceptionResolver
的 doResolveHandlerMethodException()
方法找到對應的異常處理方法(標注@ExceptionHandler
)進行了異常的處理,所有實際會返回一個空的ModelAndView
,外層判斷空的 ModelAndView
是直接返回 null,表示異常已經處理完畢,不需要再進行后續處理。
9. ViewResolver - 視圖解析器(渲染視圖)
以常用的 ViewResolver
實現類 InternalResourceViewResolver
進行分析。
源碼路徑:org.springframework.web.servlet.view.InternalResourceViewResolver
核心方法:resolveViewName()
源碼解析:
DispatcherServlet.resolveViewName()
ViewResolverComposite.resolveViewName()
AbstractCachingViewResolver.resolveViewName()
AbstractCachingViewResolver.createView()
UrlBasedViewResolver.loadView()
InternalResourceViewResolver.buildView()
UrlBasedViewResolver.buildView()
核心要點:由源碼可知完整的實現鏈是:AbstractCachingViewResolver
定義了緩存機制和模板方法;UrlBasedViewResolver
實現了 loadView
并提供了 buildView
模板方法;InternalResourceViewResolver
重寫了 buildView
方法以添加 InternalResourceView
特定的配置;
這種設計充分利用了模板方法模式,使得每一層都只關注自己的職責。
其實到這里已經創建了一個完整的 View
對象了, 接下來還需要調用 View
對象的 render()
方法來渲染視圖。
View.render()
是一個接口方法,不同的視圖實現類會有不同的實現。以最常見的 InternalResourceView
(用于 JSP 渲染)為例接著分析,源碼如下:
AbstractView.render()
InternalResourceView.renderMergedOutputModel()
核心要點:view.render()
這個方法是 Spring MVC 視圖渲染的核心方法,也是視圖渲染的終點,將處理結果轉換為實際的 HTTP 響應內容。
常見的
10. LocaleResolver - 地區區域解析器(國際化i18n)
以常用的 LocaleResolver
實現類 AcceptHeaderLocaleResolver
進行分析。
源碼路徑:org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
核心方法:resolveLocale()
源碼解析:
AcceptHeaderLocaleResolver.resolveLocale()
核心要點:LocaleResolver
的實現類提供了不同的區域設置解析策略,開發者可以根據應用需求選擇合適的實現。調用鏈路從 DispatcherServlet
初始化開始,貫穿整個請求處理過程,最終在視圖渲染時使用解析到的區域設置。
三、請求處理全流程剖析
關鍵流程說明:
- 請求分發:DispatcherServlet 接收所有請求
- 處理器映射:通過 HandlerMapping 找到匹配的 Controller 方法
- 參數解析:HandlerAdapter 使用 ArgumentResolvers 解析方法參數
- 業務執行:調用 Controller 業務邏輯
- 返回值處理:使用 ReturnValueHandlers 處理返回值
- 視圖解析:ViewResolver 將邏輯視圖名解析為具體 View
- 視圖渲染:View 對象渲染響應內容
四、核心設計模式應用
1. 策略模式(組件可插拔)
public interface HandlerMapping {HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}public interface HandlerAdapter {boolean supports(Object handler);ModelAndView handle(...) throws Exception;
}
- 不同實現類處理不同類型的處理器
- 可通過配置替換默認實現
- 運行時動態選擇適配器
2. 模板方法模式(流程標準化)
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter {public final ModelAndView handle(...) throws Exception {// 固定處理流程checkRequest(request);return handleInternal(request, response, handlerMethod);}// 子類實現具體邏輯protected abstract ModelAndView handleInternal(...) throws Exception;
}
3. 責任鏈模式(攔截器棧)
public class HandlerExecutionChain {private final List<HandlerInterceptor> interceptorList = new ArrayList<>();boolean applyPreHandle(...) {// 順序執行攔截器前置處理for (HandlerInterceptor interceptor : interceptorList) {if (!interceptor.preHandle(request, response, this.handler)) {return false;}}return true;}
}
五、擴展機制實戰
1. 自定義參數解析器
public class CustomArgumentResolver implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(CustomAnnotation.class);}@Overridepublic Object resolveArgument(...) {// 自定義參數解析邏輯return customValue;}
}// 注冊到Spring容器
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {resolvers.add(new CustomArgumentResolver());}
}
2. 自定義視圖解析器
public class CustomViewResolver implements ViewResolver {@Overridepublic View resolveViewName(String viewName, Locale locale) throws Exception {if (viewName.startsWith("custom:")) {return new CustomView(); // 自定義視圖實現}return null; // 交給其他解析器處理}
}
六、性能優化設計
1. 映射緩存機制
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping {// 映射關系緩存private final MappingRegistry mappingRegistry = new MappingRegistry();class MappingRegistry {// URL到HandlerMethod的映射緩存private final Map<String, MappingRegistration<T>> registry = new HashMap<>();// 方法簽名緩存private final Map<HandlerMethod, T> mappingLookup = new LinkedHashMap<>();}
}
2. 快速失敗機制
public class DispatcherServlet extends FrameworkServlet {protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {try {// 處理流程...} catch (Exception ex) {// 快速捕獲異常processDispatchResult(..., ex);}}
}
3. 性能優化方案
@Configuration
public class PerformanceConfig {// 限制上傳文件大小@Beanpublic MultipartResolver multipartResolver() {CommonsMultipartResolver resolver = new CommonsMultipartResolver();resolver.setMaxUploadSize(1024 * 1024 * 10); // 10MBreturn resolver;}// 啟用GZIP壓縮@Beanpublic FilterRegistrationBean<GzipFilter> gzipFilter() {FilterRegistrationBean<GzipFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new GzipFilter());registration.addUrlPatterns("/*");return registration;}
}
七、Spring MVC 設計精髓總結
- 組件化架構:9大核心組件各司其職;通過策略接口實現松耦合
- 擴展點豐富:14+擴展接口覆蓋請求處理全生命周期;支持自定義參數解析、返回值處理等
- 分層處理:清晰的請求處理流水線
- 性能優化:映射關系緩存 + 懶加載機制 + 快速失敗處理
- 與現代技術融合:無縫支持 RESTful、完美整合 WebSocket、兼容響應式編程模型
- 設計模式典范:前端控制器模式統一入口 + 策略模式實現組件替換 + 模板方法模式固定流程
Spring MVC的優雅不僅在于功能強大,更在于其精心設計的擴展性和可維護性。理解其底層架構,能讓我們在復雜業務場景中游刃有余。
End!
擴展
MultipartResolver Diagram
LocaleResolver Diagram
ThemeResolver Diagram
HandlerMapping Diagram
HandlerAdapter Diagram
HandlerExceptionResolver Diagram
RequestToViewNameTranslator Diagram
ViewResolver Diagram
FlashMapManager Diagram