博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。 ② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。 ③ 群内也有职场精英,大厂大佬,跨国企业主管,可交流技术、面试、找工作的经验。 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬,进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。 群公告里还有全网大赛约稿汇总/博客提效工具集/CSDN自动化运营脚本 有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。文章目录
- Spring 机制六: MVC 全链路源码解析:从 DispatcherServlet 到返回值解析(超硬核源码深度)
- 目录
- 1. Spring MVC 架构与整体链路总览
- 2. DispatcherServlet 初始化流程(源码解析)
- DispatcherServlet#onRefresh
- initStrategies 装配 MVC 全套组件
- 3. 请求分发核心:doDispatch
- 4. HandlerMapping:如何找到 Controller?
- RequestMappingHandlerMapping 工作流程
- 5. HandlerAdapter:如何调用 Controller 方法?
- HandlerAdapter 调用链源码
- 6. 参数解析器(ArgumentResolver)内部原理
- 7. 返回值处理器(ReturnValueHandler)链路
- 8. 拦截器执行顺序
- 9. Controller 调用链全景图
- 10. Spring MVC 与 AOP 如何协作
- 11. 实战:自定义参数解析器
- 1)定义注解
- 2)自定义解析器
- 3)注册解析器
- 4)Controller 使用
- 12. 超级总图:Spring MVC 全链路流程图
- 13. 参考文档
- 结束语
Spring 机制六: MVC 全链路源码解析:从 DispatcherServlet 到返回值解析(超硬核源码深度)
目录
- Spring MVC 的整体架构与执行链路总览
- DispatcherServlet 初始化流程(源码)
- 请求分发核心:doDispatch 全链路解析
- HandlerMapping 的查找过程
- HandlerAdapter 的适配与调用
- 参数解析器(Argument Resolver)内部原理
- 返回值处理器(ReturnValueHandler)链路
- 拦截器执行顺序
- Controller 方法调用链全景图(Mermaid)
- 与 AOP 如何协同
- 实战:自定义参数解析器
- Mermaid 超级总图:从请求进入到响应输出
- 参考文档
1. Spring MVC 架构与整体链路总览
Spring MVC 的核心处理流程可以抽象为:
HTTP 输入 → DispatcherServlet → HandlerMapping → HandlerAdapter → 参数解析 → 调用 Controller 方法 → 返回值解析 → 视图解析 → HTTP 输出
整体流程 Mermaid 展示:
2. DispatcherServlet 初始化流程(源码解析)
DispatcherServlet 是 Spring MVC 核心入口点,继承链:
FrameworkServlet → HttpServletBean → HttpServletDispatcherServlet#onRefresh
@OverrideprotectedvoidonRefresh(ApplicationContextcontext){initStrategies(context);}initStrategies 装配 MVC 全套组件
protectedvoidinitStrategies(ApplicationContextcontext){initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);}重点:
- HandlerMapping
- HandlerAdapter
- ViewResolver
都是在这里完成自动装配,属于 MVC 的“预热阶段”。
3. 请求分发核心:doDispatch
核心路径:
FrameworkServlet#doService → DispatcherServlet#doDispatch简化源码:
protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse){HandlerExecutionChainmappedHandler=getHandler(request);HandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());if(!mappedHandler.applyPreHandle(request,response)){return;}ModelAndViewmv=ha.handle(request,response,mappedHandler.getHandler());mappedHandler.applyPostHandle(request,response,mv);processDispatchResult(request,response,mappedHandler,mv);}4. HandlerMapping:如何找到 Controller?
职责:
根据 URL 找到对应 Controller 的 HandlerMethod
常见 HandlerMapping:
| 类型 | 用途 |
|---|---|
| RequestMappingHandlerMapping | 处理 @RequestMapping 体系 |
| BeanNameUrlHandlerMapping | Bean 名称即 URL |
| SimpleUrlHandlerMapping | XML 配置 URL |
Spring Boot 默认使用 RequestMappingHandlerMapping。
RequestMappingHandlerMapping 工作流程
启动时扫描所有@Controller/@RestController+@RequestMapping方法,构建:
Map<RequestMappingInfo, HandlerMethod>请求时执行:
publicHandlerExecutionChaingetHandler(HttpServletRequestrequest){returnthis.mappingRegistry.getMappings().entrySet().stream().filter(entry->entry.getKey().getPatternsCondition().match(request)).findFirst().map(entry->newHandlerExecutionChain(entry.getValue())).orElse(null);}5. HandlerAdapter:如何调用 Controller 方法?
Spring MVC 支持多种 HandlerAdapter:
| Adapter | 用途 |
|---|---|
| RequestMappingHandlerAdapter | 注解 Controller 方法调用 |
| HttpRequestHandlerAdapter | 支持 HttpRequestHandler |
| SimpleControllerHandlerAdapter | 早期 Controller 模式 |
默认使用 RequestMappingHandlerAdapter,负责:
- 参数绑定
- 参数解析器链
- 返回值解析器链
- 调用 HandlerMethod
HandlerAdapter 调用链源码
publicModelAndViewhandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler){returninvokeHandlerMethod(request,response,(HandlerMethod)handler);}6. 参数解析器(ArgumentResolver)内部原理
核心类:HandlerMethodArgumentResolverComposite
流程:
foreach parameter:1.找到 supportsParameter=true的 resolver2.调用 resolver.resolveArgument()常见解析器:
| 解析器 | 用途 |
|---|---|
| RequestParamMethodArgumentResolver | @RequestParam |
| PathVariableMethodArgumentResolver | @PathVariable |
| RequestResponseBodyMethodProcessor | @RequestBody |
| ServletRequestMethodArgumentResolver | HttpServletRequest |
源码执行:
publicObjectresolveArgument(...){HandlerMethodArgumentResolverresolver=getResolver(parameter);returnresolver.resolveArgument(parameter,mavContainer,request,binderFactory);}7. 返回值处理器(ReturnValueHandler)链路
控制器方法返回值交给 HandlerMethodReturnValueHandlerComposite
常见解析器:
| 类型 | 用途 |
|---|---|
| RequestResponseBodyMethodProcessor | @ResponseBody |
| ModelAndViewMethodReturnValueHandler | ModelAndView |
| ViewNameMethodReturnValueHandler | 视图名 |
| HttpEntityMethodProcessor | ResponseEntity |
| CallableMethodReturnValueHandler | 异步 Callable |
源码流程:
HandlerMethodReturnValueHandlerhandler=selectHandler(returnType);handler.handleReturnValue(returnValue,returnType,mavContainer,request);8. 拦截器执行顺序
HandlerExecutionChain:
preHandle() → Controller → postHandle() → afterCompletion()源码示例:
if(!interceptor.preHandle())return;handler.invoke();interceptor.postHandle();interceptor.afterCompletion();preHandle 顺序执行,afterCompletion 倒序执行,类似异常栈。
9. Controller 调用链全景图
10. Spring MVC 与 AOP 如何协作
AOP 代理发生在 BeanPostProcessor 阶段:
- Controller 本身是代理对象
- HandlerMapping 匹配的 HandlerMethod 是代理方法
- AOP 的 MethodInterceptor 包裹 Controller 调用
请求链路:
HTTP → DispatcherServlet → HandlerAdapter → AOP Proxy → Controller11. 实战:自定义参数解析器
目标:自动解析 HeaderX-User-Id
1)定义注解
@Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)public@interfaceUserId{}2)自定义解析器
publicclassUserIdArgumentResolverimplementsHandlerMethodArgumentResolver{@OverridepublicbooleansupportsParameter(MethodParameterparameter){returnparameter.hasParameterAnnotation(UserId.class);}@OverridepublicObjectresolveArgument(MethodParameterparameter,ModelAndViewContainermavContainer,NativeWebRequestwebRequest,WebDataBinderFactorybinderFactory){returnwebRequest.getHeader("X-User-Id");}}3)注册解析器
@ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddArgumentResolvers(List<HandlerMethodArgumentResolver>resolvers){resolvers.add(newUserIdArgumentResolver());}}4)Controller 使用
@GetMapping("/me")publicStringme(@UserIdStringuid){return"uid="+uid;}12. 超级总图:Spring MVC 全链路流程图
13. 参考文档
- Spring MVC 官方文档
https://docs.spring.io/spring-framework/reference/web/webmvc.html - Spring Framework GitHub
https://github.com/spring-projects/spring-framework - HandlerMethod 官方说明
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/method/HandlerMethod.html
结束语
👨💻 关于我
持续学习 | 追求真我
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
掘金点击访问Qiuner CSDN点击访问Qiuner GitHub点击访问Qiuner Gitee点击访问Qiuner
| 专栏 | 简介 |
|---|---|
| 📊 一图读懂系列 | 图文并茂,轻松理解复杂概念 |
| 📝 一文读懂系列 | 深入浅出,全面解析技术要点 |
| 🌟持续更新 | 保持学习,不断进步 |
| 🎯 人生经验 | 经验分享,共同成长 |
你好,我是Qiuner.为帮助别人少走弯路而写博客
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
代码都在Github或Gitee上,如有需要可以去上面自行下载。记得给我点星星哦😍
如果你遇到了问题,自己没法解决,可以去我掘金评论区问。CSDN评论区和私信消息看不完 掘金消息少一点.
| 上一篇推荐 | 链接 |
|---|---|
| Java程序员快又扎实的学习路线 | 点击该处自动跳转查看哦 |
| 一文读懂 AI | 点击该处自动跳转查看哦 |
| 一文读懂 服务器 | 点击该处自动跳转查看哦 |
| 2024年创作回顾 | 点击该处自动跳转查看哦 |
| 一文读懂 ESLint配置 | 点击该处自动跳转查看哦 |
| 老鸟如何追求快捷操作电脑 | 点击该处自动跳转查看哦 |
| 未来会写什么文章? | 预告链接 |
|---|---|
| 一文读懂 XX? | 点击该处自动跳转查看哦 |
| 2025年终总结 | 点击该处自动跳转查看哦 |
| 一图读懂 XX? | 点击该处自动跳转查看哦 |