文章目录
- 一、设计哲学:分层与解耦
- 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