spring高级篇(八)
本篇对Spring MVC 的执行流程做一个简单总结
MVC执行流程总结
当浏览器发送一个请求,例如http://localhost:8080/hello,请求到达服务器后,一般会进行如下操作:
1、首先会经过DispatcherServlet,默认映射路径为 /,即会匹配到所有请求 URL,可作为请求的统一入口,也被称之为前控制器(jsp 不会匹配到 DispatcherServlet )
非Spring Boot 程序,需要手动进行创建,此前的案例中已多次演示:
/*** 创建DispatcherServlet* @return*/@Beanpublic DispatcherServlet dispatcherServlet(){return new DispatcherServlet();}
Spring Boot 程序,由 DispatcherServletAutoConfiguration 进行自动装配:

DispatcherServlet默认是在首次使用时,由tomcat容器初始化,也可以进行设置setLoadOnStartup() 为启动时初始化:
/*** 注册DispatcherServlet springmvc入口* @param dispatcherServlet* @return*/@Beanpublic DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet,WebMvcProperties webMvcProperties){DispatcherServletRegistrationBean registrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/");//设置tomcat容器启动时即进行DispatcherServlet初始化registrationBean.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());return registrationBean;}
DispatcherServlet 初始化时会优先到容器里寻找各种组件,作为它的成员变量:
下面的init方法有一个共同点:首先会去父子容器中寻找有无相关组件,如果没有会使用默认的组件:

- HandlerMapping :初始化时记录映射关系。(初始化时,会收集所有映射信息,封装为 Map)
- HandlerAdapter :初始化时准备参数解析器、返回值处理器、消息转换器 。(分派请求)
- HandlerExceptionResolver :初始化时准备参数解析器、返回值处理器、消息转换器。(处理异常)
- ViewResolver :准备视图处理
容器初始化时,会收集所有 @RequestMapping 映射信息,封装为 Map:
// RequestMappingHandlerMapping 初始化时,会收集所有 @RequestMapping 映射信息,封装为 Map
// k:请求方式 路径{ /test4} v 方法信息com.itbaima.a18.Controller1#test4()Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();handlerMethods.forEach((k,v)->{System.out.println( k + "=" + v);});
2、DispatcherServlet 会利用HandlerMapping 的实现去查找控制器方法,我们使用最常用的 RequestMappingHandlerMapping 举例:
- 根据 /hello 路径找到 @RequestMapping("/hello") 对应的控制器方法
- 控制器方法会被封装为 HandlerMethod 对象,并结合匹配到的拦截器一起返回给 DispatcherServlet
- HandlerMethod 和拦截器合在一起称为 HandlerExecutionChain(调用链)对象
//发送请求了,根据路径K 获取RequestMappingHandlerMapping 封装的 Map 对应的V HandlerMethod
//获取的结果会包装在拦截器链中
//HandlerExecutionChain with [com.itbaima.a18.Controller1#test1()] and 0 interceptors
HandlerExecutionChain chain = handlerMapping.getHandler(request);
3、DispatcherServlet 接下来会:
调用拦截器的 preHandle 方法:如果与preHandle方法中定义的拦截规则不匹配,就直接返回错误信息,不再向下执行。
RequestMappingHandlerAdapter 调用 handle 方法,准备数据绑定工厂、模型工厂、ModelAndViewContainer、将 HandlerMethod 完善为 ServletInvocableHandlerMethod:

- @ControllerAdvice 全局增强点1️:补充模型数据,通过解析@ModelAttribute 标注的方法补充模型数据到container中。
@ControllerAdvicestatic class MyControllerAdvice {@ModelAttribute("a")public String aa() {return "aa";}}/*** ModelAttribute注解加在参数上,由参数解析器负责解析* 加在方法上,由HandlerAdapt进行解析*/@Controllerstatic class Controller1 {@ResponseStatus(HttpStatus.OK)public ModelAndView foo(@ModelAttribute("u") User user) {System.out.println("foo");return null;}}
- @ControllerAdvice 全局增强点2:补充自定义类型转换器,通过@InitBinder 注解标记一个用于初始化DataBinder对象,自定义数据绑定行为的方法,它会在控制器处理请求之前被调用。(如果@InitBinder注解加在被@ControllerAdvice 注解标记的控制器类的方法中时,其作用范围是全局的,并且是由RequestMappingHandlerAdapter 在初始化时解析并记录。而@InitBinder 注解加在被@Controller 标记的控制器中的方法上时,会在控制器方法首次执行时解析并记录。
@ControllerAdvicestatic class MyControllerAdvice {@InitBinderpublic void binder3(WebDataBinder webDataBinder) {webDataBinder.addCustomFormatter(new MyDateFormatter("binder3 转换器"));}}@Controllerstatic class Controller1 {@InitBinderpublic void binder1(WebDataBinder webDataBinder) {webDataBinder.addCustomFormatter(new MyDateFormatter("binder1 转换器"));}public void foo() {}}
RequestMappingHandlerAdapter中有两个成员变量:
- private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache:用于存储被@ControllerAdvice标记的控制器中 @InitBinder 标注的方法。
- private final Map<Class<?>, Set<Method>> initBinderCache:用于存储@Controller 标记的控制器中@InitBinder标注的方法。


然后会使用 HandlerMethodArgumentResolver 准备参数
- @ControllerAdvice 全局增强点3:RequestBody 增强
调用 ServletInvocableHandlerMethod 、使用 HandlerMethodReturnValueHandler 处理返回值。
- @ControllerAdvice 全局增强点4:ResponseBody 增强
ResponseBody返回响应体前包装:
@ControllerAdvicestatic class MyResponseAdvice implements ResponseBodyAdvice<Object> {/*** 支持的方法** @param returnType 返回值类型* @param converterType 转换类型* @return*/@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {//如果方法上加了ResponseBody注解,或者类上加了ResponseBody/RestController注解,才进行转换if (returnType.getMethodAnnotation(ResponseBody.class) != null|| AnnotationUtils.findAnnotation(returnType.getContainingClass(), ResponseBody.class) != null) {return true;}return false;}/*** 增强的逻辑** @param body 返回值* @param returnType 返回类型* @param selectedContentType 所选的响应内容类型。* @param selectedConverterType 所选的消息转换器类型。* @param request 当前的请求对象。* @param response 当前的响应对象。* @return*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//如果返回值就是Result类型则直接返回if (body instanceof Result) {return body;}//否则包装成Result类型返回return Result.ok(body);}}
最后会根据 ModelAndViewContainer 获取 ModelAndView:
- 返回值处理器调用了 HttpMessageConverter 来将结果转换为 JSON,这时 ModelAndView 就为 null
- 如果返回的 ModelAndView 为 null,不会进行后续的视图渲染与解析。
ModelAndView、String、未被@ResponseBody 注解控制的对象类型返回值(无论是否显式声明了@ModelAttribute),都要经历视图渲染的过程。
ModelAndView找视图,是根据ModelAndView构造中的viewName寻找同名的视图,还会使用.addObject() 方法中指定的数据对视图进行渲染 。
如果没有指定视图名,则会:
根据请求路径推断视图名: 如果在处理器方法中没有显式指定视图名,Spring MVC 会根据请求路径来推断视图名。
根据返回值类型推断视图名: 如果处理器方法的返回值类型是String类型,并且没有使用 @ResponseBody 注解,Spring MVC 会将返回的字符串作为视图名处理。
默认视图名: 如果以上两种方式都没有找到视图名,Spring MVC 会使用默认的视图名。默认的视图名通常是处理器方法所在的类名转换而来,再加上适当的前后缀。String找视图,是根据返回值的名称去找同名的视图。
未被@ResponseBody 注解控制的对象类型返回值,找视图时,如果方法上使用 @RequestMapping("/") 及其派生注解声明了路径,则按照路径的值去匹配视图。如果没有,则需要手动指定路径。
HttpEntity、HttpHeaders、加上了@ResponseBody 注解的对象返回值类型,因为对应解析器的handleReturnValue 方法中标记了请求已经被处理,无需继续渲染视图,所以不走渲染视图流程。其区别在于返回的响应头和响应体的完整性。
4、调用拦截器的 postHandle 方法
5、处理异常或视图渲染
- @ControllerAdvice 全局增强点5️:@ExceptionHandler 异常处理
6、调用拦截器的 afterCompletion 方法
相关文章:
spring高级篇(八)
本篇对Spring MVC 的执行流程做一个简单总结 MVC执行流程总结 当浏览器发送一个请求,例如http://localhost:8080/hello,请求到达服务器后,一般会进行如下操作: 1、首先会经过DispatcherServlet,默认映射路径为 /&…...
UP互助 帮助UP起号做视频 支持B站和抖音
【软件名字】:UP互助 【软件版本】:1.0 【软件大小】:17.5MB 【软件平台】:安卓 【测试机型】:小米9 1.随便登个邮箱,添加自己平台的频道,然后就可以帮助别人,添加频道后在添加…...
*求问?:为何会超时(TLE)?
D - Grid and Magnet (atcoder.jp) 错误代码: //2024年5月5日14:53:43 #include <bits/stdc.h> #define move mmove //防止与头文件中重复 using namespace std; int h,w; string s[1000]; const int move[4][2]{{1,0},{-1,0},{0,1},{0,-1}}; bool used[100…...
cocosstudio工程文件(.ccs)维护问题
创建cocos工程.bat在多人合作的cocos项目中,大家公用一个ccs文件,存在的问题是如果大家都提交ccs文件比较容易出现冲突,解决冲突麻烦要耗费时间,不提交的话就拉不到其他人更新的csd文件。 方案一 解决冲突,更新提交c…...
Blender动画与云渲染:创造高质量作品的未来路径
Blender作为开源的3D图形软件,在多个领域广受欢迎。但随着项目复杂度提升,传统渲染方式受限。云渲染技术的兴起突破了这些限制,为创作者提供了更自由、高效的创作环境。 一、Blender动画项目的挑战 传统上,Blender动画渲染需要依…...
【MySQL】3.MySQL核心概念解析:数据完整性、事务处理、索引及聚簇索引与非聚簇索引
探索MySQL的内部机制,理解数据完整性、事务处理、索引策略以及聚簇索引与非聚簇索引的区别是至关重要的。这些概念构成了数据库设计和优化的基础,对于确保数据的准确性、提高查询效率、维护数据的一致性和实现复杂的数据库操作至关重要。本文将逐一剖析这…...
【netty系列-03】深入理解NIO的基本原理和底层实现(详解)
Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478【三】深入理解NIO的基本原理和底层…...
大数据Scala教程从入门到精通第二篇:Scala入门
一:Scala入门 1:为什么学习Scala Spark新一代内存级大数据计算框架,是大数据的重要内容 Spark就是使用Scala编写的。因此为了更好的学习Spark,需要掌握Scala这门语言 Spark的兴起,带动Scala语言的发展! 2:Scala的发展…...
Spring Data JPA数据批量插入、批量更新真的用对了吗
Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 前言 在前两篇文章已经…...
数据结构-线性表-应用题-2.2-12
1)算法的基本设计思想:依次扫描数组的每一个元素,将第一个遇到的整数num保存到c中,count记为1,若遇到的下一个整数还是等于num,count,否则count--,当计数减到0时,将遇到的下一个整数保存到c中,计…...
目录页码右对齐快速解决
选择目录–段落–制表符,按图中设置即可...
分红76.39亿,分红率再创新高,成长活力无限的伊利带来丰厚回报
伊利47万股东,又等来了一个好消息。 4月29日,伊利股份发布2023年报,实现营业总收入1261.79亿元,归母净利润104.29亿元,双创历史新高,实现连续31年稳健增长。 在递交亮眼成绩单的同时,乳业巨头伊…...
关于行进线路。
https://map.tianditu.gov.cn/ 作者:Chockhugh 链接:https://www.zhihu.com/question/20545559/answer/494685117 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 以50km,几乎全是…...
Unity 编辑器工具 - 资源引用查找器
目录 1.功能概述 2.完整代码 3. 实现原理 4. 使用预览 5.新增优化版本 在Unity项目开发过程中,管理和维护资源之间的引用关系是至关重要的。当然我们项目也是需要这个功能 毕竟项目大了之后查找资源引用还是交给 资源引用查找器 比较好。 1.功能概述 资源引用…...
MySQL中的批量更新实战
MySQL中的批量更新实战 表结构 mysql> desc dept; --------------------------------------------------------- | Field | Type | Null | Key | Default | Extra | --------------------------------------------------------- | deptno | int(11) …...
为软件教学文档增加实践能力
为了更方便软件教学,我们在凌鲨(OpenLinkSaas)上增加了公共资源引用的功能。 目前可以被引用的公共资源: 微应用常用软件公共知识库Docker模板 引用公共资源 引用微应用 目前微应用包含了主流数据库,终端等工具,可以方便的进行各种相关实…...
39-2 Web应用防火墙 - WAF数据库层绕过
如果你本地没有安装mysql就先安装一下:4-2 MySQL 的下载与安装_mysql5.7.9.1下载-CSDN博客 一、数据库层绕过简介 绕过数据库层通常用于规避Web应用防火墙(WAF)的SQL注入防护规则。攻击者需要利用数据库特性,寻找规避常规安全策略的方法。这里涉及到不同数据库的特性、SQ…...
薪酬激励策略:留住企业核心人才的关键
在竞争激烈的商业环境中,企业为了保持竞争力和市场地位,必须高度重视人才的管理和发展。企业的核心人才是推动企业发展的关键因素,因此,如何有效地激励和留住这些核心人才,成为企业持续发展的关键之一。薪酬激励策略作…...
【bbs02补】注册功能form组件-前端-后端-总结、登录功能(前端、后端、生成验证码)
1 注册功能 1.1 注册功能form组件 1.2 注册功能前端 1.3 注册功能后端 1.4 forms组件和前后端总结 2 登录功能 2.1 登录前端 2.2 生成验证码 1 注册功能 1.1 注册功能form组件 # 注册页面-用户名-密码-确认密码-邮箱-手机号-头像# form组件 可以帮助我们1 快速生成前端页面2 数…...
MindSponge分子动力学模拟——定义一个分子系统
技术背景 在前面两篇文章中,我们分别介绍了分子动力学模拟软件MindSponge的软件架构和安装与使用。这里我们进入到实用化阶段,假定大家都已经在本地部署好了基于MindSpore的MindSponge的编程环境,开始用MindSponge去做一些真正的分子模拟的工…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
