第六篇・Spring 5 源码深度拆解:SpringMVC 全流程核心原理
👋前言
前面几篇,我们已经把Spring 容器、Bean 生命周期、AOP、事务 四大核心底层全部打通。而 Web 开发中最核心的 SpringMVC,本质就是:在 Web 容器(Tomcat)启动时初始化 Spring 容器,再通过一套统一的分发机制,把 HTTP 请求转发到对应的 @Controller 方法。
接下来基于 Spring 源码,主要介绍以下几个问题:
1.@EnableWebMvc到底干了什么?
2.请求从浏览器进来,完整经过哪些组件?
3.HandlerMapping、HandlerAdapter、ViewResolver 分别干嘛用?
4.参数是怎么绑定到方法入参的?
5.返回值是怎么变成 JSON / 页面 / 异常信息的?
6.拦截器、异常处理器在源码中哪个节点执行?
从请求入口到视图渲染,彻底搞懂Web 底层执行链路
一、核心前提:SpringMVC 整体架构
1. 一句话概括流程
浏览器请求→ DispatcherServlet分发→找到对应 Controller 方法→执行方法 →处理返回值 →响应给浏览器
2. 九大核心组件(面试必背)
|
组件 |
作用 |
|
HandlerMapping |
根据请求URL找到对应的Controller方法 |
|
HandlerAdapter |
统一执行Controller方法的适配器 |
|
ThemeResolver |
不同主题间动态切换 |
|
ViewResolver |
视图解析器,把逻辑视图名转为真实视图 |
|
HandlerExceptionResolver |
全局异常处理器 |
|
LocaleResolver |
国际化解析器 |
|
MultipartResolver |
文件上传解析器 |
|
RequestToViewNameTranslator |
默认视图名转换器 |
|
FlashMapManager |
重定向数据管理器 |
二、入口:@EnableWebMvc源码解析
@EnableWebMvc是JavaConfig 方式手动启用 SpringMVC 的注解,等价于 XML 中的<mvc:annotation-driven/>- Spring Boot 项目不推荐、也不需要加它。
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import(DelegatingWebMvcConfiguration.class)public @interface EnableWebMvc {}
核心就是导入:DelegatingWebMvcConfiguration
它会自动向容器注册:
- RequestMappingHandlerMapping
- RequestMappingHandlerAdapter
- ExceptionHandlerExceptionResolver
- 各种参数解析器、返回值处理器
- 消息转换器(MappingJackson2HttpMessageConverter)
一句话:@EnableWebMvc = 自动装配 SpringMVC 全套核心组件
三、容器启动:SpringMVC 初始化流程
1. Tomcat 启动 → 加载 DispatcherServlet
DispatcherServlet 本质是一个 Servlet,生命周期:init() → service() → destroy()
2. init 阶段核心:初始化九大组件
protected void initStrategies(ApplicationContext context) {initMultipartResolver(context); // 文件上传initLocaleResolver(context); // 国际化initThemeResolver(context);initHandlerMappings(context); // 路由映射initHandlerAdapters(context); // 执行适配器initHandlerExceptionResolvers(context); // 异常处理initRequestToViewNameTranslator(context);initViewResolvers(context); // 视图解析initFlashMapManager(context);}
这就是 SpringMVC 启动时干的所有事。
四、请求执行全流程
浏览器发送 HTTP 请求↓Tomcat 接收请求,交给 DispatcherServlet↓doService(req, resp)↓doDispatch(req, resp) 【核心总调度方法】↓1. getHandler(request)→ 遍历 HandlerMapping,找到对应 Controller 方法↓2. getHandlerAdapter(handler)→ 找到能执行该方法的适配器↓3. 执行拦截器 applyPreHandle -> 调用 preHandle↓4. adapter.handle(request, response, handler)→ 真正执行 Controller 方法↓内部:参数解析 → 执行方法 → 得到返回值↓5. 处理返回值(JSON/视图/文件等)↓6. 执行拦截器 applyPostHandle ->调用 postHandle↓7. 异常处理(执行异常解析器)↓8. 渲染视图(如果不是直接响应)↓9. 执行拦截器 triggerAfterCompletion ->调用 afterCompletion↓响应回浏览器
五、核心方法
doDispatch 源码部分内容如下
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;try {ModelAndView mv = null;Exception dispatchException = null;try {// 1. 找到对应的处理器(Controller方法)mappedHandler = getHandler(processedRequest);// 2. 找到适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 3. 执行拦截器 preHandleif (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 4. 【真正调用Controller方法】mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 5. 执行拦截器 postHandlemappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}// 6. 处理结果、渲染视图、异常处理processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {// 最终拦截器mappedHandler.triggerAfterCompletion(processedRequest, response, ex);}}
六、关键节点深度拆解
1. 根据 URL 找到 Controller 方法
流程图位置: doDispatch → 1. getHandler(request)
所在类:org.springframework.web.servlet.DispatcherServlet
所在方法:doDispatch
mappedHandler = getHandler(processedRequest);
核心实现:
- 遍历容器中所有
HandlerMapping - 由
RequestMappingHandlerMapping负责匹配 - 建立并返回
url → HandlerMethod的映射 - 封装为
HandlerExecutionChain(包含所有拦截器)
2. 找到执行方法的适配器
流程图位置: doDispatch → 2. getHandlerAdapter(handler)
所在类:DispatcherServlet
所在方法:doDispatch
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
核心实现:
- 遍历所有
HandlerAdapter - 匹配到
RequestMappingHandlerAdapter继承自 AbstractHandlerMethodAdapter - 用于统一执行
@RequestMapping方法
3. 执行拦截器 preHandle
流程图位置: doDispatch → 3. 执行拦截器 preHandle
所在类:DispatcherServlet
所在方法:doDispatch
if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}
实际执行类:HandlerExecutionChain
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptors.size(); i++) {HandlerInterceptor interceptor = this.interceptors.get(i);if (!interceptor.preHandle(request, response, this.handler)) {triggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;}
关键点:任一拦截器返回 false,直接中断请求,并执行已通过拦截器afterCompletion。
4. 真正执行 Controller 方法
流程图位置: doDispatch → 4. adapter.handle(…)
所在类:DispatcherServlet
所在方法:doDispatch
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
实际执行类:RequestMappingHandlerAdapter
4.1 参数解析
调度入口:RequestMappingHandlerAdapter
执行类:ServletInvocableHandlerMethod
遍历所有参数解析器,处理:
- @RequestParam
- @PathVariable
- @RequestBody
- @RequestHeader
- ServletRequest / HttpServletResponse
4.2 反射执行目标方法
所在类:InvocableHandlerMethod方法:doInvoke
return method.invoke(getBean(), getArguments());
ha.handle()↓handleInternal()↓invokeHandlerMethod()↓invocableMethod.invokeAndHandle()↓invokeForRequest()↓【doInvoke()】 ← 最终执行到这里↓method.invoke(bean, args) → 反射调用Controller方法
5. 处理返回值(JSON / 视图)
流程图位置: 执行方法后 → 5. 处理返回值
所在类:ServletInvocableHandlerMethod
方法:invokeAndHandle
核心组件:HandlerMethodReturnValueHandlerComposite
常见实现:
RequestResponseBodyMethodProcessor:处理 @ResponseBody → JSONViewNameMethodReturnValueHandler:处理字符串视图名ModelAndViewMethodReturnValueHandler:处理 ModelAndView
6. 执行拦截器 postHandle
流程图位置: doDispatch → 6. 执行拦截器 postHandle
所在类:DispatcherServlet所在方法:doDispatch
mappedHandler.applyPostHandle(processedRequest, response, mv);
实际执行类:HandlerExecutionChain
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {for (int i = this.interceptors.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptors.get(i);interceptor.postHandle(request, response, this.handler, mv);}}
注意:逆序执行。
preHandle:正序执行
postHandle:逆序执行
afterCompletion:逆序执行
7. 渲染视图
流程图位置: doDispatch → 7. 渲染视图
所在类:DispatcherServlet所在方法:processDispatchResult
render(mv, request, response);
逻辑:
- 通过 ViewResolver 解析视图名得到 View
- 执行 view.render (model, request, response)
- 适用于 JSP/Thymeleaf/Freemarker 等模板
8. 执行拦截器 afterCompletion
流程图位置: doDispatch → 8. 执行拦截器 afterCompletion
所在类:DispatcherServlet位置: doDispatch 最终 catch 块
mappedHandler.triggerAfterCompletion(processedRequest, response, ex);
实际执行类:HandlerExecutionChain
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptors.get(i);interceptor.afterCompletion(request, response, this.handler, ex);}}
关键点:无论正常返回还是抛异常,一定执行。
七、高频面试题
- SpringMVC 执行流程是什么?
1. Tomcat 启动,初始化 DispatcherServlet2. 加载 Spring 容器,注册所有 SpringMVC 组件3. 请求进入 doDispatch4. 根据 URL 找到 Controller 方法5. 执行拦截器前置6. 参数解析 → 调用方法7. 处理返回值(JSON/视图)8. 执行拦截器后置9. 渲染/响应10. 最终拦截器
- DispatcherServlet 作用?答:统一入口,总调度,管理九大组件。
- HandlerMapping 和 HandlerAdapter 区别?答:Mapping 找方法,Adapter 执行方法。
- @ResponseBody 原理?答:返回值处理器 + JSON 消息转换器。
- 拦截器和过滤器区别?答: Filter:Servlet 规范,所有容器都支持,拦截所有请求 ;Interceptor 是 SpringMVC 组件,能访问 Spring 容器。
- 参数是如何注入的?答:ArgumentResolver 链式解析。
下篇预告
下一篇我们进入 Spring Boot 自动配置原理
@SpringBootApplication三大注解拆解@EnableAutoConfiguration如何实现自动装配- SPI 机制、spring.factories
- 自定义 Starter 原理与实现
夜雨聆风