当前位置: 首页 > news >正文

Spring MVC 底层工作流程+源码分析

Spring MVC 将DispatcherServlet作为前端控制器,所有请求都先汇聚于此,再由它委派给其他组件协同处理。


Spring MVC 核心流程图

Spring MVC 核心工作流程(含源码关键调用点)

ViewResolver 视图解析

DispatcherServlet 核心调度

1. 找处理器

2. 返回 HandlerExecutionChain

3. 找适配器

4. 返回 HandlerAdapter

5. 前置拦截

若 false 则中断

若 true 继续

执行业务方法

返回 ModelAndView 或直接响应

6. 后置拦截

7. 处理结果渲染

8. 视图解析与渲染

9. 最终响应

10. 清理资源

HTTP Request

返回

doDispatch 入口

getHandler 遍历 HandlerMapping

getHandlerAdapter 获取匹配的 HandlerAdapter

applyPreHandle 执行拦截器 preHandle

HandlerAdapter.handle 执行 Controller 方法

applyPostHandle 执行拦截器 postHandle

processDispatchResult 处理结果和异常

render 视图渲染

triggerAfterCompletion 拦截器 afterCompletion

Controller / @RequestMapping 方法

resolveViewName 逻辑名 → View 对象

View.render 输出 HTML/JSON


流程详解(对照源码行号)

步骤角色 / 关键代码位置说明
1DispatcherServlet.doDispatch()line 920+所有请求入口,开始调度。
2getHandler()-> 遍历handlerMappings通过 URL 找到HandlerExecutionChain(含Handler+Interceptor列表)。
3getHandlerAdapter()根据Handler类型找到能执行它的适配器(如RequestMappingHandlerAdapter)。
4applyPreHandle()依次执行每个拦截器的preHandle方法,若返回false则请求短路。
5ha.handle()适配器调用实际Controller方法(通过反射),并封装返回值为ModelAndView
6applyPostHandle()执行拦截器的postHandle方法(在Controller之后、视图渲染之前)。
7processDispatchResult()统一处理ModelAndView或异常。
8render()->ViewResolver.resolveViewName()根据逻辑视图名(如"userList")解析出View(如InternalResourceView)。
9View.render()将模型数据与视图合并(如 JSP 渲染),输出到HttpResponse
10triggerAfterCompletion()执行拦截器的afterCompletion方法(无论是否异常,最终清理)。

图中使用了子图DispatcherServletViewResolver,并用不同颜色区分组件类型,流程箭头清晰标注了步骤序号,方便和源码对应。


精简版总结(一句话 + 一张表)

DispatcherServlet 接收请求 → HandlerMapping 定位 → HandlerAdapter 执行 → 拦截器干预 → 返回 ModelAndView → ViewResolver 渲染 → 输出响应

阶段组件源码方法
接收请求DispatcherServletdoDispatch()
定位处理器HandlerMappinggetHandler()
执行处理器HandlerAdapterha.handle()
视图解析ViewResolverresolveViewName()
视图渲染Viewrender()
拦截器回调InterceptorpreHandle/postHandle/afterCompletion

组件分析

核心组件(五大关键角色)

组件职责
DispatcherServlet中央调度器,接收请求并分发给其他组件
HandlerMapping根据请求 URL 找到能处理它的Handler(即@RequestMapping方法)
HandlerAdapter适配器:确保不同类型的Handler能以统一方式被调用执行
ViewResolver根据逻辑视图名(如"hello")解析出真正的View对象(如hello.jsp
View负责视图渲染,将Model数据填充到视图中

执行流程:源码逐步拆解

1. 请求入口:doDispatch(Request, Response)

DispatcherServletdoDispatch是处理所有请求的核心调度方法:

protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{HttpServletRequestprocessedRequest=request;HandlerExecutionChainmappedHandler=null;ModelAndViewmv=null;// ... 上下文设置、异步处理等 ...try{// ✅ 1. 检查文件上传processedRequest=checkMultipart(request);// ✅ 2. 获取处理器执行链 (Handler + Interceptors)mappedHandler=getHandler(processedRequest);if(mappedHandler==null){noHandlerFound(processedRequest,response);return;}// ✅ 3. 获取支持该 Handler 的适配器HandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());// ✅ 4. 执行所有拦截器的 preHandle 方法if(!mappedHandler.applyPreHandle(processedRequest,response)){return;// 如果某个拦截器返回 false,流程中断}// ✅ 5. 核心!调用 Handler 执行业务逻辑,返回 ModelAndViewmv=ha.handle(processedRequest,response,mappedHandler.getHandler());// ✅ 6. 执行所有拦截器的 postHandle 方法mappedHandler.applyPostHandle(processedRequest,response,mv);// ✅ 7. 最终视图渲染与异常处理processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);}catch(Exceptionex){// 统一异常处理}}

2. 处理器映射:getHandler(Request)

以下代码展示了如何为请求找到匹配的处理器:

protectedHandlerExecutionChaingetHandler(HttpServletRequestrequest){for(HandlerMappinghm:this.handlerMappings){HandlerExecutionChainhandler=hm.getHandler(request);if(handler!=null){returnhandler;// 返回包含 Handler 和拦截器链的对象}}returnnull;}

3. 获取适配器:getHandlerAdapter(Handler)

以下代码展示了如何获取适配器:

protectedHandlerAdaptergetHandlerAdapter(Objecthandler){for(HandlerAdapterha:this.handlerAdapters){if(ha.supports(handler)){returnha;}}thrownewServletException("No adapter for handler...");}

4. 业务执行:ha.handle(...) -> ModelAndView

适配器的handle方法内部会:

  • 解析请求参数与@PathVariable
  • 执行数据验证与类型转换
  • 通过反射调用Controller的具体方法
  • 将返回值(数据、视图名)封装为ModelAndView对象

5. 最终响应:processDispatchResult(...)

processDispatchResult方法会调用ViewResolverModelAndView中的逻辑视图名解析为物理视图(如 JSP),并执行渲染。

privatevoidprocessDispatchResult(HttpServletRequestrequest,HttpServletResponseresponse,HandlerExecutionChainmappedHandler,ModelAndViewmv,Exceptionexception)throwsException{// 统一异常处理// ...if(mv!=null){// 调用 ViewResolver 解析逻辑视图名render(mv,request,response);}// 执行所有拦截器的 afterCompletion 方法if(mappedHandler!=null){mappedHandler.triggerAfterCompletion(request,response,null);}}

一个请求进来,从前到后的核心处理链就完整走通了:DispatcherServletHandlerMapping定位方法 →HandlerAdapter适配执行 → 反射调用业务代码,返回ModelAndViewViewResolverView渲染响应 → 中间穿插着Interceptor的拦截逻辑。

DispatcherServlet类比为公司的前台总机,所有访客(请求)先到这里。总机根据来意查看地图(HandlerMapping)找到对应部门,找到后安排行政助理(HandlerAdapter)对接,业务办完后秘书将结果返回前台,再由总机指定专员(ViewResolver)制作最终的回执文件(View)交给访客。

http://www.jsqmd.com/news/784384/

相关文章:

  • 办公地址位于珠海的澳门公司注册机构 -珠海凯旋 - 速递信息
  • SAP VF02/VF03屏幕增强实战:在发票抬头添加自定义子屏幕(含BADI_SD_CUST_HEAD完整代码)
  • 01华夏之光永存・开源:黄大年茶思屋榜文解法「22期 1题」 超高密度磁存储技术研究|当期专项完整解法
  • CANN/opbase贡献指南
  • 别再只懂RGB了!从sRGB到Lab,5分钟搞懂设计师和程序员都该知道的色彩空间转换
  • 2026玻璃钢水箱厂家怎么选?口碑好、实力强的品牌权威盘点 - 深度智识库
  • 2026主管护师听谁的课?5位宝藏老师实测,过考考生亲证高效 - 医考机构品牌测评专家
  • 常州汽车线束波纹管定制 vs 标准品:2026年5大源头厂家深度测评 - 企业名录优选推荐
  • CANN/ops-cv源码构建指南
  • YOLOv2真的过时了吗?在树莓派4B上部署YOLOv2-Tiny做实时监控,实测FPS和精度对比
  • 国家知识产权局新规:这些 AI 人工智能专利不能申请!
  • DuckyClaw:基于TuyaOpen C SDK的轻量级AI智能体硬件实现
  • 2026年常州热缩管源头厂家深度横评:从标准品到定制化解决方案的产业升级 - 企业名录优选推荐
  • 2026年贵阳防雷检测与防雷工程完全指南:甲级资质机构深度横评 - 年度推荐企业名录
  • 2026 年 5 月液压传感器十大品牌厂家实力排名,东莞南力高稳适配严苛工况 - 品牌速递
  • 企业捐赠AI开源项目背后的三重激励:社会、经济与技术逻辑
  • 2026年探秘:霞浦口碑美食推荐,究竟哪店铺独占鳌头? - 速递信息
  • 2026年功能性机油选购全攻略:破解烧机油痛点的权威推荐 - 博客湾
  • CANN算子测试挑战赛总决赛提交
  • 2026巴厘岛目的地婚礼星级排名TOP10:佩尼达岛到乌鲁瓦图全境权威测评 - charlieruizvin
  • 2026年贵阳防雷检测与防雷工程:甲级资质权威机构深度横评及官方直达指南 - 年度推荐企业名录
  • 2026年泰州干洗店大起底:权威测评排名全揭秘 - 速递信息
  • AlphaOPT:自我进化的大语言模型优化系统解析
  • 意识研究新范式:从被动观察到主动构建的认知革命
  • #2026最新软化水设备公司推荐!陕西西安甘肃兰州等地靠谱机构榜单 - 十大品牌榜
  • 常州轨道交通阻燃编织网管2026年深度测评:昶力管业等5大厂家对标分析 - 企业名录优选推荐
  • 镜像视界(浙江)科技 数字孪生与视频孪生行业地位及核心优势
  • 2026年5月压力传感器十大品牌厂家权威发布,东莞南力稳居行业前列 - 品牌速递
  • 2026淮南干洗店大揭秘:权威测评与排名全解析 - 速递信息
  • Godot游戏开发瑞士军刀:bitbrain/godot-gamejam工具集深度解析与应用指南