Spring MVC 核心工作原理:DispatcherServlet 全流程深度

1 阅读7分钟

Spring MVC 作为 Spring 框架的核心 Web 模块,其核心调度器 DispatcherServlet 贯穿了从应用启动到请求处理的全生命周期。理解 DispatcherServlet 的加载机制与请求处理流程,是掌握 Spring MVC 设计思想和排查 Web 开发问题的关键。本文将从概述、加载机制、核心流程、关键组件细分流程四个维度,全面拆解 Spring MVC 的工作原理。

一、概述

Spring MVC 的核心设计思想是「前端控制器模式」,DispatcherServlet 作为整个 Web 应用的前端控制器,承担着请求分发、组件协调的核心职责。其完整工作流程可划分为两大核心阶段:

  1. 初始化阶段DispatcherServlet 的创建、配置与注册到 Web 服务器(如 Tomcat)的过程,确保应用启动后 DispatcherServlet 具备处理请求的能力;
  2. 请求处理阶段:当客户端发起 HTTP 请求时,DispatcherServlet 协调各类组件完成请求解析、业务处理、响应渲染的全链路流程。 这两个阶段环环相扣,初始化阶段为请求处理提供了基础环境,请求处理阶段则是 DispatcherServlet 核心能力的具体体现。

二、DispatcherServlet 的加载机制(初始化阶段)

DispatcherServlet 并非直接由开发者手动创建和注册,而是通过 Spring Boot 的自动配置机制与 Web 服务器的启动流程联动,完成加载与注册。整个过程依赖三大核心对象,并分为「容器注入」和「服务器注册」两步执行。

(一)核心依赖对象

  1. DispatcherServletRegistrationBeanServletContextInitializer 接口的实现类,核心职责是将 DispatcherServlet 封装为 Tomcat 可识别的 Servlet 注册信息,包括 Servlet 名称、映射路径(默认 /)、加载顺序等,最终将 DispatcherServlet 交给 Tomcat 管理。
  2. DispatcherServletAutoConfiguration:Spring Boot 自动配置类(位于 spring-boot-autoconfigure 包中),通过条件注解(@ConditionalOnWebApplication 等)确保仅在 Web 环境下生效。该类内部定义了两个关键 Bean 的创建逻辑:
  • dispatcherServlet():创建 DispatcherServlet 实例,并注入默认配置(如主题、视图解析器等);
  • dispatcherServletRegistration():创建 DispatcherServletRegistrationBean 实例,关联上述 DispatcherServlet 并配置默认映射规则。
  1. TomcatStarterServletContainerInitializer 接口的实现类,作为 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 细分流程(请求映射与拦截)

HandlerMappingDispatcherServlet 寻找处理器的核心组件,负责「URL 匹配→拦截器执行→处理器返回」的关键逻辑,直接决定了请求该交给哪个 Controller 方法处理。

(一)核心依赖组件

  1. HandlerInterceptor:拦截器,用于在请求到达 Controller 之前、之后以及视图渲染完成后执行自定义逻辑(如登录验证、日志记录),支持链式调用;
  2. CorsConfiguration:跨域配置信息,用于判断请求是否允许跨域,支持自定义允许的 Origin、Method、Header 等;
  3. UrlPathHelper:URL 路径解析工具,负责从请求中提取真实的访问路径(如排除上下文路径、Servlet 路径后的路径);
  4. PathMatcher:路径匹配工具,负责判断解析后的 URL 路径是否与 Controller 方法上 @RequestMapping 注解配置的路径规则匹配(支持 Ant 风格路径,如 /user/*/order/{id})。

(二)组件配置方式

各组件均提供默认实现,开发者可通过以下方式自定义配置:

  • 实现 WebMvcConfigurer 接口,重写 addInterceptors()(添加拦截器)、addCorsMappings()(配置跨域)等方法;
  • 自定义 UrlPathHelperPathMatcher 实例并注入 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 调用→返回值处理」。

(一)核心依赖组件

  1. HttpMessageConverter:消息转换器,负责 HTTP 请求体与 Java 对象的相互转换(如将 JSON 格式的请求体转换为 User 对象,将 User 对象转换为 JSON 响应),支持 application/jsonapplication/xml 等格式;
  2. HandlerMethodArgumentResolver:方法参数解析器,负责从请求中提取参数并转换为 Handler 方法所需的参数类型(如解析 @RequestParam@PathVariable@RequestBody 标注的参数);
  3. HandlerMethodReturnValueHandler:返回值处理器,负责处理 Handler 方法的返回值(如将 ModelAndView 交给视图解析器,将 @ResponseBody 标注的返回值通过 HttpMessageConverter 转换为 JSON);
  4. WebDataBinder:数据绑定器,负责将请求参数转换为目标对象的属性(如将请求参数 username 绑定到 User 对象的 username 字段),并支持数据校验(如通过 @Valid 注解触发校验);
  5. ModelMap:数据模型容器,用于存储 Handler 方法执行过程中产生的响应数据,最终传递给视图进行渲染(如在 JSP 中通过 ${model.key} 访问数据)。

(二)组件配置方式

  1. HttpMessageConverter、HandlerMethodArgumentResolver、HandlerMethodReturnValueHandler
  • 默认提供多种实现(如 MappingJackson2HttpMessageConverter 处理 JSON 转换);
  • 实现 WebMvcConfigurer 接口,重写 extendMessageConverters()addArgumentResolvers()addReturnValueHandlers() 方法自定义扩展。
  1. WebDataBinder
  • 全局配置:通过 @ControllerAdvice 配合 @InitBinder 注解,配置所有 Controller 共享的数据绑定规则;
  • 局部配置:在具体 Controller 中通过 @InitBinder 注解,配置当前 Controller 专属的绑定规则。
  1. 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 主导的「组件化协同」模式:通过自动配置机制完成初始化加载,确保应用启动后具备请求处理能力;通过标准化的组件分工(映射、适配、解析、渲染),实现请求处理的全链路解耦。 理解这一流程的关键在于:

  1. 初始化阶段:DispatcherServlet 如何通过 Spring Boot 自动配置注入容器,并注册到 Tomcat;
  2. 请求处理阶段:DispatcherServlet 如何协调各组件,按「映射→拦截→参数解析→业务执行→返回值处理→视图渲染」的顺序完成请求响应;
  3. 组件扩展:各核心组件均支持自定义配置,开发者可通过实现 WebMvcConfigurer、@ControllerAdvice 等方式灵活扩展功能。

掌握这些原理,不仅能帮助开发者快速定位 Web 开发中的问题(如请求映射失败、参数解析异常、跨域问题),更能深入理解 Spring 框架「约定优于配置」「解耦复用」的设计思想。