Spring MVC 作为 Spring 框架的核心 Web 模块,其核心调度器 DispatcherServlet 贯穿了从应用启动到请求处理的全生命周期。理解 DispatcherServlet 的加载机制与请求处理流程,是掌握 Spring MVC 设计思想和排查 Web 开发问题的关键。本文将从概述、加载机制、核心流程、关键组件细分流程四个维度,全面拆解 Spring MVC 的工作原理。
一、概述
Spring MVC 的核心设计思想是「前端控制器模式」,DispatcherServlet 作为整个 Web 应用的前端控制器,承担着请求分发、组件协调的核心职责。其完整工作流程可划分为两大核心阶段:
- 初始化阶段:
DispatcherServlet的创建、配置与注册到 Web 服务器(如 Tomcat)的过程,确保应用启动后DispatcherServlet具备处理请求的能力; - 请求处理阶段:当客户端发起 HTTP 请求时,
DispatcherServlet协调各类组件完成请求解析、业务处理、响应渲染的全链路流程。 这两个阶段环环相扣,初始化阶段为请求处理提供了基础环境,请求处理阶段则是DispatcherServlet核心能力的具体体现。
二、DispatcherServlet 的加载机制(初始化阶段)
DispatcherServlet 并非直接由开发者手动创建和注册,而是通过 Spring Boot 的自动配置机制与 Web 服务器的启动流程联动,完成加载与注册。整个过程依赖三大核心对象,并分为「容器注入」和「服务器注册」两步执行。
(一)核心依赖对象
- DispatcherServletRegistrationBean:
ServletContextInitializer接口的实现类,核心职责是将DispatcherServlet封装为 Tomcat 可识别的 Servlet 注册信息,包括 Servlet 名称、映射路径(默认/)、加载顺序等,最终将DispatcherServlet交给 Tomcat 管理。 - DispatcherServletAutoConfiguration:Spring Boot 自动配置类(位于
spring-boot-autoconfigure包中),通过条件注解(@ConditionalOnWebApplication等)确保仅在 Web 环境下生效。该类内部定义了两个关键 Bean 的创建逻辑:
dispatcherServlet():创建DispatcherServlet实例,并注入默认配置(如主题、视图解析器等);dispatcherServletRegistration():创建DispatcherServletRegistrationBean实例,关联上述DispatcherServlet并配置默认映射规则。
- TomcatStarter:
ServletContainerInitializer接口的实现类,作为 Spring Boot 与 Tomcat 之间的桥梁,负责将 Spring 容器中的ServletContextInitializer(含DispatcherServletRegistrationBean)对应的 Servlet 注册到 Tomcat 的 Servlet 容器中。
(二)加载核心步骤
步骤 1:DispatcherServlet 注入 Spring 容器
Spring Boot 启动时,通过自动配置机制完成 DispatcherServlet 及其注册 Bean 的容器注入,流程如下:
graph TD
A(Spring Boot 应用启动) --> B("扫描类路径下 META-INF/spring.factories 文件<br/>加载自动配置类列表 , 匹配 DispatcherServletAutoConfiguration")
B --> |"满足 Web 环境条件 @ConditionalOnWebApplication"| C(执行 )
步骤 2:从 Spring 容器到 Tomcat 注册
Spring 容器初始化完成后,通过 Web 服务器工厂创建 Tomcat 实例,并将 DispatcherServlet 注册到 Tomcat 中,流程如下:
graph TD
A(Spring Boot 启动流程进入上下文刷新阶段) --> B("初始化 AnnotationConfigServletWebServerApplicationContext 上下文")
B --> C("调用上下文 refresh() 方法,触发 Web 服务器创建")
C --> D("执行 onRefresh() 钩子方法,识别 Web 环境并准备创建服务器")
D --> E("调用 createWebServer() 方法,获取 TomcatServletWebServerFactory 实例")
E --> F("执行 TomcatServletWebServerFactory.getWebServer() 方法,创建 Tomcat 服务器实例")
F --> G("调用 prepareContext() 方法,初始化 Tomcat 的 Context 上下文(代表一个 Web 应用)")
G --> H("调用 configureContext() 方法,配置 Context 的 Servlet 注册器")
H --> I("实例化 TomcatStarter 对象,传入 Spring 容器中的 ServletContextInitializer 列表(含 DispatcherServletRegistrationBean)")
I --> J("调用 Context.addServletContainerInitializer(start) 方法,将 TomcatStarter 注册到 Tomcat")
J --> K("Tomcat 启动时,触发 TomcatStarter.onStartup() 方法<br/>通过 DispatcherServletRegistrationBean 将 DispatcherServlet 注册到 Tomcat 的 Servlet 容器")
K --> L("DispatcherServlet 初始化完成,监听 Tomcat 端口,等待接收请求")
三、请求处理核心流程
当客户端发起 HTTP 请求(如 GET/POST),请求经 Tomcat 接收后转发给 DispatcherServlet,此时进入核心处理流程。DispatcherServlet 本身不直接处理业务逻辑,而是通过协调多个功能组件,完成请求的解析、处理、响应全链路。
(一)核心组件说明
DispatcherServlet 依赖的组件均遵循「容器优先,默认兜底」的原则:优先从 Spring 容器中获取自定义组件,若容器中无对应 Bean,则使用 Spring MVC 提供的默认实现。各核心组件功能如下:
| 组件名称 | 核心职责 | 默认实现 |
|---|---|---|
| FlashMapManager | 管理重定向时的临时数据(如 redirectAttributes),避免重定向后请求数据丢失 | SessionFlashMapManager |
| MultipartResolver | 处理 content-type=multipart/form-data 类型请求,支持文件上传 | StandardServletMultipartResolver |
| HandlerMapping | 根据请求 URL 匹配对应的处理器(Handler,通常是 Controller 方法),同时获取拦截器链(HandlerInterceptor) | RequestMappingHandlerMapping(处理 @RequestMapping 注解) |
| HandlerAdapter | 适配不同类型的 Handler,负责请求参数解析、Handler 调用、返回值处理 | RequestMappingHandlerAdapter(适配 @Controller 注解的处理器) |
| RequestToViewNameTranslator | 当 Handler 未返回 View 时,根据请求 URL 自动生成默认视图名 | DefaultRequestToViewNameTranslator |
| LocaleResolver | 解析请求的区域信息(如语言、时区),支持多语言国际化 | AcceptHeaderLocaleResolver(从请求头 Accept-Language 解析) |
| ViewResolver | 将逻辑视图名(如 "index")解析为物理视图(如 JSP、HTML 或模板页面),完成页面渲染 | InternalResourceViewResolver(默认解析 JSP) |
| ThemeResolver | 解析应用主题(如样式、资源文件),支持动态切换前端样式 | FixedThemeResolver |
| HandlerExceptionResolver | 捕获 Handler 执行过程中抛出的异常,统一进行异常处理(如返回错误页面、JSON 错误信息) | ExceptionHandlerExceptionResolver(处理 @ExceptionHandler 注解) |
(二)核心流程执行链路
DispatcherServlet 协调各组件处理请求的完整流程如下,组件执行顺序严格遵循「预处理→业务处理→后处理→响应渲染」的逻辑:
graph TD
A("客户端发起 HTTP 请求,Tomcat 转发给 DispatcherServlet") --> B("DispatcherServlet 调用 FlashMapManager<br/>恢复重定向携带的临时数据(FlashMap),并清理过期数据")
B --> C("调用 MultipartResolver<br/>判断请求是否为文件上传类型,若为则解析 multipart 数据,封装为 MultipartHttpServletRequest")
C --> D("调用 HandlerMapping<br/>根据请求 URL、请求方法(GET/POST)匹配对应的 Handler(Controller 方法)和拦截器链")
D --> E("调用 HandlerAdapter<br/>适配 Handler,解析请求参数(如 @RequestParam、@RequestBody),调用 Handler 执行业务逻辑")
E --> F("Handler 执行完成后,返回 ModelAndView(含视图名和响应数据)或其他返回值(如 @ResponseBody 标注的 JSON 数据)")
F --> G("若 Handler 未返回 View,调用 RequestToViewNameTranslator<br/>根据请求 URL 生成默认视图名")
G --> H("调用 LocaleResolver<br/>解析请求的区域信息,为视图渲染提供多语言支持")
H --> I("调用 ViewResolver<br/>将逻辑视图名解析为物理视图对象(如 JSP 视图、Thymeleaf 视图)")
I --> J("调用 ThemeResolver<br/>解析当前主题,为视图渲染提供样式支持")
J --> K("视图对象渲染页面,将 Model 中的数据填充到视图中,生成 HTTP 响应")
K --> L("响应返回客户端,请求处理完成")
M("若流程中抛出异常,调用 HandlerExceptionResolver<br/>捕获异常并处理(如返回错误视图、JSON 错误响应),跳转至响应流程")
E -->|抛出异常| M
D -->|未找到 Handler| M
四、HandlerMapping 细分流程(请求映射与拦截)
HandlerMapping 是 DispatcherServlet 寻找处理器的核心组件,负责「URL 匹配→拦截器执行→处理器返回」的关键逻辑,直接决定了请求该交给哪个 Controller 方法处理。
(一)核心依赖组件
- HandlerInterceptor:拦截器,用于在请求到达 Controller 之前、之后以及视图渲染完成后执行自定义逻辑(如登录验证、日志记录),支持链式调用;
- CorsConfiguration:跨域配置信息,用于判断请求是否允许跨域,支持自定义允许的 Origin、Method、Header 等;
- UrlPathHelper:URL 路径解析工具,负责从请求中提取真实的访问路径(如排除上下文路径、Servlet 路径后的路径);
- PathMatcher:路径匹配工具,负责判断解析后的 URL 路径是否与 Controller 方法上
@RequestMapping注解配置的路径规则匹配(支持 Ant 风格路径,如/user/*、/order/{id})。
(二)组件配置方式
各组件均提供默认实现,开发者可通过以下方式自定义配置:
- 实现
WebMvcConfigurer接口,重写addInterceptors()(添加拦截器)、addCorsMappings()(配置跨域)等方法; - 自定义
UrlPathHelper或PathMatcher实例并注入 Spring 容器,覆盖默认实现。
(三)细分执行流程
graph TD
A("DispatcherServlet 调用 HandlerMapping.getHandler(HttpServletRequest request)") --> B("UrlPathHelper.getLookupPathForRequest(request)<br/>解析请求 URL,提取真实访问路径(如请求 URL 为 http://localhost:8080/app/user/1,提取后为 /user/1)")
B --> C("CorsConfiguration 校验跨域请求<br/>判断请求 Origin、Method 是否在允许列表中,若不允许则直接返回跨域错误")
C --> D("PathMatcher.matches()<br/>将解析后的路径与所有 Controller 方法的 @RequestMapping 路径规则匹配<br/>匹配成功则获取对应的 Handler(HandlerMethod 实例,封装 Controller 方法信息)")
D --> E("获取该 Handler 对应的拦截器链(HandlerInterceptor 列表)")
E --> F("按拦截器注册顺序执行拦截器 preHandle() 方法<br/>若某一拦截器 preHandle() 返回 false,中断请求流程,直接返回响应")
F -->|"所有拦截器 preHandle() 均返回 true"| G("将 Handler 和拦截器链返回给 DispatcherServlet,后续由 HandlerAdapter 调用 Handler")
G --> H("Handler(Controller 方法)执行完成后,按拦截器注册的逆序执行 postHandle() 方法<br/>可修改 ModelAndView 中的数据或视图信息")
H --> I("视图渲染完成后,按拦截器逆序执行 afterCompletion() 方法<br/>用于资源清理(如关闭流、释放锁)")
五、HandlerAdapter 细分流程(参数解析与返回值处理)
HandlerAdapter 是适配器模式的典型应用,负责适配不同类型的 Handler(如 @Controller 注解的方法、HttpRequestHandler),解决 DispatcherServlet 与 Handler 之间的通信问题,核心职责是「参数解析→Handler 调用→返回值处理」。
(一)核心依赖组件
- HttpMessageConverter:消息转换器,负责 HTTP 请求体与 Java 对象的相互转换(如将 JSON 格式的请求体转换为 User 对象,将 User 对象转换为 JSON 响应),支持
application/json、application/xml等格式; - HandlerMethodArgumentResolver:方法参数解析器,负责从请求中提取参数并转换为 Handler 方法所需的参数类型(如解析
@RequestParam、@PathVariable、@RequestBody标注的参数); - HandlerMethodReturnValueHandler:返回值处理器,负责处理 Handler 方法的返回值(如将
ModelAndView交给视图解析器,将@ResponseBody标注的返回值通过 HttpMessageConverter 转换为 JSON); - WebDataBinder:数据绑定器,负责将请求参数转换为目标对象的属性(如将请求参数
username绑定到 User 对象的username字段),并支持数据校验(如通过@Valid注解触发校验); - ModelMap:数据模型容器,用于存储 Handler 方法执行过程中产生的响应数据,最终传递给视图进行渲染(如在 JSP 中通过
${model.key}访问数据)。
(二)组件配置方式
- HttpMessageConverter、HandlerMethodArgumentResolver、HandlerMethodReturnValueHandler:
- 默认提供多种实现(如
MappingJackson2HttpMessageConverter处理 JSON 转换); - 实现
WebMvcConfigurer接口,重写extendMessageConverters()、addArgumentResolvers()、addReturnValueHandlers()方法自定义扩展。
- WebDataBinder:
- 全局配置:通过
@ControllerAdvice配合@InitBinder注解,配置所有 Controller 共享的数据绑定规则; - 局部配置:在具体 Controller 中通过
@InitBinder注解,配置当前 Controller 专属的绑定规则。
- ModelMap:
- 全局配置:通过
@ControllerAdvice配合@ModelAttribute注解,向所有 Controller 的 Model 中添加全局共享数据; - 局部配置:在具体 Controller 中通过
@ModelAttribute注解,向当前 Controller 的 Model 中添加数据。
(三)细分执行流程
graph TD
A("DispatcherServlet 调用 HandlerAdapter.handle(HttpServletRequest request, HttpServletResponse response, Object handler)") --> B("判断 Handler 类型(此处以 @Controller 注解的 HandlerMethod 为例)")
B --> C("初始化 WebDataBinder<br/>根据全局/局部 @InitBinder 配置,设置数据绑定规则和校验器")
C --> D("调用 HandlerMethodArgumentResolver 链<br/>逐个解析 Handler 方法的参数:")
D --> D1("解析 @RequestParam:从请求参数中提取值并转换为参数类型")
D --> D2("解析 @PathVariable:从 URL 路径中提取占位符值并转换")
D --> D3("解析 @RequestBody:通过 HttpMessageConverter 将请求体(如 JSON)转换为 Java 对象")
D --> D4("解析 @CookieValue、@SessionAttribute 等:从 Cookie、Session 中提取参数")
D --> D5("参数绑定过程中,通过 WebDataBinder 完成类型转换和数据校验(如 @Valid 标注的参数)")
D --> E("所有参数解析完成后,调用 Handler 方法(Controller 业务方法)执行业务逻辑")
E --> F("获取 Handler 方法的返回值(如 ModelAndView、JSON 对象、String 视图名)")
F --> G("调用 HandlerMethodReturnValueHandler 链<br/>处理返回值:")
G --> G1("若返回 ModelAndView:直接传递给后续视图渲染流程")
G --> G2("若返回 @ResponseBody 标注的对象:通过 HttpMessageConverter 转换为 JSON/XML 等格式,写入响应体")
G --> G3("若返回 String:判断为逻辑视图名,封装为 ModelAndView")
G --> G4("处理过程中,将响应数据存入 ModelMap,供视图渲染使用")
G --> H("返回处理结果(ModelAndView 或直接写入响应体),流程结束")
总结
Spring MVC 的核心是 DispatcherServlet 主导的「组件化协同」模式:通过自动配置机制完成初始化加载,确保应用启动后具备请求处理能力;通过标准化的组件分工(映射、适配、解析、渲染),实现请求处理的全链路解耦。
理解这一流程的关键在于:
- 初始化阶段:
DispatcherServlet如何通过 Spring Boot 自动配置注入容器,并注册到 Tomcat; - 请求处理阶段:DispatcherServlet 如何协调各组件,按「映射→拦截→参数解析→业务执行→返回值处理→视图渲染」的顺序完成请求响应;
- 组件扩展:各核心组件均支持自定义配置,开发者可通过实现 WebMvcConfigurer、@ControllerAdvice 等方式灵活扩展功能。
掌握这些原理,不仅能帮助开发者快速定位 Web 开发中的问题(如请求映射失败、参数解析异常、跨域问题),更能深入理解 Spring 框架「约定优于配置」「解耦复用」的设计思想。