spring5源码篇(12)——spring-mvc请求流程

spring-framework 版本:v5.3.19

文章目录

  • 一、请求流程
    • 1、处理器映射器
      • 1.1、 RequestMappingHandlerMapping
      • 1.2、获取对应的映射方法
      • 1.3、添加拦截器
    • 2、获取合适的处理器适配器
    • 3、通过处理器适配器执行处理器方法
      • 3.1、拦截器的前置后置
      • 3.2、处理器的执行
        • 3.2.1 参数解析器解析参数和执行处理器方法
        • 3.2.2 结果处理器处理结果
        • 3.2.3 消息转化器
    • 4、视图解析器
  • 二、请求流程中的一些问题
  • 1、各种组件如处理器映射器,处理器适配器,视图解析器等是如何注入到spring容器的?
  • 2、RequestMappingInfoHandlerMapping 处理器映射器中维护的映射map (即MapingRegister) 是如何初始化的?
  • 3、处理器映射器中的拦截器是如何添加的?
  • 4、处理器适配器的参数解析器和结果处理器是如何来的?
  • 5、参数解析器/结果处理器中的消息转化器是如何来的?

一、请求流程

总体流程在 DispatchServelt#doDispatch 方法
在这里插入图片描述

1、处理器映射器

首先会获取根据url去映射对应的处理器(即接口执行方法)
看到对应的 getHandler 方法
在这里插入图片描述
为方便阅读,进入debug。可以看到springmvc默认为我们注册了三个handlerMapping。

springMvc中的各个组件如处理器映射器,处理器适配器,视图解析器等是如何注入到容器的,先暂时不看,第二部分在看(问题1)。

1.1、 RequestMappingHandlerMapping

而其中我们最常用的一个就是RequestMappingHandlerMapping,所以这里只看这个类的 getHandler 方法(其实也是其抽象父类的方法)。
在这里插入图片描述

1.2、获取对应的映射方法

getHandlerInternal 方法入手,看看是如何把一个请求映射到对应的方法的。
在这里插入图片描述
这里首先会从 mappingRegister 中去找可以根据url直接得到的映射(即没有替换符),如果找不到再去所有注册的映射中找,然后返回一个最匹配的映射对应的处理器。

mappingRegister 可以简单的理解成 Map<url,handler>。实际上,为提供效率一共维护了3个map
在这里插入图片描述
这些map是如何初始化的,第二部分再讲(问题2)。

至于是如何匹配这些映射的,从 addMatchingMappings 入手
在这里插入图片描述
这里其实就是把匹配逻辑抽象成一个个condition,如果满足所有 condition 说明这是一个可用的处理器。注意,仅是可用而已,并不一定会用这个处理器。因为可能同时会匹配到多个可用的处理器,但是最终只会返回最匹配的那一个。

1.3、添加拦截器

在前面的总体流程中注释到,获取处理器的时候,返回的是一个处理器链。因为可能会配置有拦截器,而拦截器的添加从 getHandlerExecutionChain 入手。
在这里插入图片描述
可以看到,就只是遍历当前 handlerMapping 所添加的所有拦截器,若匹配,则将该拦截器添加到处理器链中而已。至于 handlerMapping 的拦截器是如何添加的,第二部分再讲(问题3)。

2、获取合适的处理器适配器

在这里插入图片描述
Spring MVC可能会有多种类型的处理器,例如控制器(Controller)、RESTful控制器等。处理器适配器负责选择并调用合适的处理器来处理请求。这一步就是去获取一个合适的处理器适配器,其实就是一个简单遍历获取,在spring mvc 默认提供的几种适配器中,最常用的还是 RequestMappingHandlerAdapter

3、通过处理器适配器执行处理器方法

3.1、拦截器的前置后置

在正式看处理器之前,顺便提一嘴拦截器的执行。
在执行实际业务方法之前会先执行处理器链中拦截器前置方法。同理,执行完业务方法后会执行处理器链中拦截器的后置方法。
在这里插入图片描述
拦截器的执行就是一个遍历,就不上代码了。

3.2、处理器的执行

ha.handle 入手
在这里插入图片描述
不管是哪种适配器,最终都会依次通过 参数解析器、处理器、结果处理器 将方法返回值封装成 ModelAndView 对象。

3.2.1 参数解析器解析参数和执行处理器方法

从 invokeForRequest 入手
在这里插入图片描述
处理器方法的执行就是反射实现的,没啥好看的。主要看参数解析器是如何解析参数的。
在这里插入图片描述
InvocableHandlerMethod 中维护了名为 resolvers 的 HandlerMethodArgumentResolverComposite 对象(多个参数解析器的封装),并且这个变量的值是处理器适配器传过来的。至于处理器适配器的参数解析器是哪来的,先暂时不看,后面第二部分再看(问题4)。这里只需知道参数解析器是在这里解析的以及值是处理器适配器传过来的就可以了。

3.2.2 结果处理器处理结果

从 returnValueHandlers.handleReturnValue 入手
在这里插入图片描述
**跟参数解析器维护的复合对象一样,也维护了一个名为 returnValueHandlers 的 HandlerMethodReturnValueHandlerComposite 复合对象,并且这个变量的值也是处理器适配器传过来的。**至于处理器适配器的结果处理器是哪来的,也先暂时不看。

一般来说参数解析器的命名为 xxxMethodArgumentResolver 而结果处理器的命名为 xxxMethodReturnValueHandler。但是如果即是参数解析器又是结果处理器的命名就会xxxMethodProcessor。而我们常用的 RequestResponseBodyMethodProcessor 就是这种类型。
在这里插入图片描述

3.2.3 消息转化器

首先并不是所有的参数解析器或者结果处理器都会用到消息转化器。,但至少我们最常用的 **RequestResponseBodyMethodProcessor 无论是解析参数还是处理结果,都会用到消息转化器。**对应的方法分别是 readWithMessageConverters,writeWithMessageConverters。并且write是直接写到 http 的response,这也意味着 @ResponseBody 不需要通过视图解析器解析渲染视图。
在这里插入图片描述

在 RequestResponseBodyMethodProcessor 中无论是read还是write,都会去遍历参数解析器/结果处理器中维护的消息转化器列表。至于 参数解析器/结果处理器的消息转化器列表是哪里来的,也先暂时不看,后面在看(问题5)。

4、视图解析器

试想这么一个接口,没有 @ResponseBody 并且返回值是一个字符串。

如果有 @ResponseBody 注解,ModelAndView为null,无需解析渲染视图。
在这里插入图片描述
在我们配置如下的视图解析器时会访问到servlet容器下的mv.html页面。
在这里插入图片描述
从字符串到返回的具体页面,这正是视图解析器所做的事情。

关于视图解析器,从 processDispatchResult 入手
在这里插入图片描述
解析:如果 ModelAndView 有视图名(在上面的例子中视图名就是方法返回的字符串)就会调用视图解析器去解析视图名得到一个视图 View 对象,反之就从 ModelAndView 中直接获取 View 对象。总之,不管怎样,这里一定要有 View 对象,没有就报错。
渲染:然后再调用上一步得到的 View 对象 render 方法并将 ModelAndView 里的 Model 数据传入,从而将数据渲染带视图上(如:jsp)。最后将渲染后的结果返回至前端。


至此一个完整的请求流程就看完了。为更形象记忆 spring mvc 各组件之间的关系,这里附上一张网图
在这里插入图片描述

二、请求流程中的一些问题

1、各种组件如处理器映射器,处理器适配器,视图解析器等是如何注入到spring容器的?

答:@EnableWebMvc注解(相当于xml配置: <mvc:annotation-driven/>)。
在这里插入图片描述
@EnableWebMvc 引入了 DelegatingWebMvcConfiguration,而这个类中就默认注入了 spring mvc 的各种组件。
比如:
在这里插入图片描述

2、RequestMappingInfoHandlerMapping 处理器映射器中维护的映射map (即MapingRegister) 是如何初始化的?

答:在 RequestMappingInfoHandlerMapping bean生命周期的 afterPropertiesSet。
在这里插入图片描述

3、处理器映射器中的拦截器是如何添加的?

答:以 RequestMappingInfoHandlerMapping 为例,在 DelegatingWebMvcConfiguration 注入处理器映射器的时就同时会去set拦截器。
在这里插入图片描述
其中 getInterceptors 代码如下
在这里插入图片描述
说白了就是 getInterceptors 方法,会依次调用所有的 WebMvcConfigurer.addInteceptors 方法将自定义配置的拦截器添加到处理器映射器中的 InterceptorRegistry。之后处理器映射器在映射处理器时,将其中匹配的拦截器添加到处理链,进而实现拦截器的效果。

正是因为自动注入的原理,所以我们平时配置spring mvc时只需注入一个实现 WebMvcConfigurer 接口的类。

但其实截至目前为止添加的还只是一个原始版本的拦截器,真正使用的拦截器是适配后的版本。
适配的时机是在处理器映射器生命周期的 setApplicationContext 方法。(最后会调用到 initApplicationContext)
在这里插入图片描述

4、处理器适配器的参数解析器和结果处理器是如何来的?

答:在 RequestMappingHandlerAdapter bean生命周期的 afterPropertiesSet。

在这里插入图片描述
具体添加了哪些参数解析器,结果处理器就不细看了,太多了…

5、参数解析器/结果处理器中的消息转化器是如何来的?

答:来自处理器适配器,而处理器适配器的消息转化器来自 WebMvcConfigurer 配置或者默认配置。

如下图:
(参数解析器/结果处理器中的消息转化器来自处理器适配器)
在这里插入图片描述
(适配器的来自 WebMvcConfigurer 配置或者默认配置)
在这里插入图片描述

至于this.configurers.configureMessageConverters(converters);
首先configurers在前面第三个问题已经看过了,就是自动注入的 WebMvcConfigurer 总和。所以这句总的来说就是依次调用所有的 WebMvcConfigurer.configureMessageConverters 方法将自定义配置的消息添加到处理器适配器中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/17096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React哲学——官方示例

在本篇技术博客中&#xff0c;我们将介绍React官方示例&#xff1a;React哲学。我们将深入探讨这个示例中使用的组件化、状态管理和数据流等核心概念。让我们一起开始吧&#xff01; 项目概览 React是一个流行的JavaScript库&#xff0c;用于构建用户界面。React的设计理念是…

QuantMania!《快乐机器学习》和《Python 从入门到入迷》作者,FRM,CAIA

王的机器主理人 王圣元 (FRM, CAIA) 某加密货币公司 Head of Quant 冬海集团 SeaMoney 建模负责人 八方咨询 量化总监 新加坡国立大学金融数学硕士 新加坡国立大学量化金融学士 《快乐机器学习》的作者 《Python 从入门到入迷》的作者 第一本书 《快乐机器学习》 第二本书《Pyt…

【图论】BFS中的最短路模型

算法提高课笔记 目录 单源最短路迷宫问题题意思路代码 武士风度的牛题意思路代码 抓住那头牛题意思路代码 多源最短路矩阵距离题意思路代码 双端队列BFS电路维修题意思路代码&#xff08;加了注释&#xff09; BFS可以解决边权为1的最短路问题&#xff0c;下面是相关例题 单源…

解决ComposerStaticInit类重复加载问题

Tp5中composer安装phpoffice后报错 Cannot declare class Composer\Autoload\ComposerStaticInit6c9266e89aa536667bf36f59ad8e6e6b, because the name is already in use 错误原因: 使用ThinkPHP5框架的项目&#xff0c;在引用某些包的时候&#xff0c;可能会通过其它包&…

位图和 DC 有什么特别之处?

相信设备上下文 (DC, Device Context) 对你来说&#xff0c;应该很熟悉。 基本工作方式是&#xff0c;你可以通过调用 SelectObject 来将画笔(Pen)&#xff0c;画刷(Brush)&#xff0c;字体(Font)和位图(Bitmap)等这些对象选入设备上下文中&#xff0c;但是&#xff0c;这里的位…

初学HTML:采用CSS绘制一幅夏天的图

下面代码使用了HTML和CSS来绘制一幅炎炎夏日吃西瓜的画面。其中&#xff0c;使用了伪元素和阴影等技巧来实现部分效果。 <!DOCTYPE html> <html> <head><title>炎炎夏日吃西瓜</title><style>body {background-color: #add8e6; /* 背景颜…

小程序原生实现左右锚点联动

效果 wxml <view classbox><scroll-view scroll-y scroll-with-animation style"width:25%"><view classnav><view wx:for"{{navList}}" wx:keyindex class"title {{index active ?select:}}"data-index{{index}} bin…

Windows下安装Hive(包安装成功)

Windows下安装Hive Hive与Hadoop的版本选择很关键&#xff0c;千万不能选错&#xff0c;否则各种报错。一、Hive下载1.1、官网下载Hive1.2、网盘下载Hive 二、解压安装包&#xff0c;配置Hive环境变量2.1、环境变量新增&#xff1a;HIVE_HOME2.2、修改Path环境变量&#xff0c;…

JVM、Redis、反射

JVM JVM是Java virtual machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是一种用于计算机的规范&#xff0c;是通过在实际计算机上仿真模拟各种计算机功能来实现的。 主要组件构成&#xff1a; 1.类加载器 子系统负责从文件系统或者网络中加载Class文件&…

深度学习实战 | 开发一个围棋智能体

01、数据模型 神经网络的训练过程需要将HD5文件中的样本数据解析出来。数据集中的棋盘局面可以提取后直接输入卷积网络进行特征提取。从属性中取出样本标签用于神经网络的损失计算和反向传播。如图1所示&#xff0c;落子方信息从属性中提取后不用参与棋盘局面的特征提取&#…

Spire.Office for.NET Crack

Spire.Office for.NET Crack Spire.Office for.NET是E-iceblue提供的企业级Office.NET API的组合。它包括Spire.Doc、Spire.XLS、Spire.Seadsheet、Spire.Presentation、Spire_PDF、Spire.DataExport、SpireOfficeViewer、Spire-PDFViewer、Spire.DocViewer、Spire.Barcode和Sp…

在linux中怎样同时运行三个微服务保证退出时不会终止

前言 1.maven中打jar包 使用插件打包,必须在pom.xml中添加插件,否则不能在linux中编译运行 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version&g…

AMEYA详解松下Panasonic HF SSOP 1 Form A AQY PhotoMOS继电器

Panasonic HF SSOP 1 Form A AQY PhotoMOS继电器采用微型SSOP封装&#xff0c;具有600V的负载电压和1500Vrms 的I/O隔离电压 这些继电器具有8Ω的低导通电阻和高速运行的特点&#xff0c;SSOP封装旨在实现高密度安装。Panasonic HF SSOP AQY PhotoMOS继电器适用于从测试和测量设…

postman和jmeter的区别何在?

小伙伴们大家好呀&#xff0c;前段时间笔者做了一个小调查&#xff0c;发现软件测试行业做功能测试和接口测试的人相对比较多。在测试工作中&#xff0c;有高手&#xff0c;自然也会有小白&#xff0c;但有一点我们无法否认&#xff0c;就是每一个高手都是从小白开始的&#xf…

柴洪峰院士:大模型赋能金融科技思考与展望

本文整理自7月7日世界人工智能大会“AI生成与垂直大语言模型的无限魅力”论坛上中国工程院院士、复旦大学金融科技研究院院长柴洪峰《大模型赋能金融科技思考与展望》的主题分享&#xff0c;从金融垂直模型构建、金融知识图谱与大模型融合以及金融大模型的监管三个方面进行介绍…

Mycat-Balance使用指南

MyCAT Balance是一个Java NIO的高性能负载均衡器&#xff0c;可以替代普通的硬件的交换机或其LVS类似的复杂机制&#xff0c;实现MyCAT集群的负载均衡。 MyCAT Balance的配置文件在conf目录下&#xff0c;frontend-conf.为前端配置&#xff0c;包括绑定的端口等&#xff0c;js…

uniapp 小程序实时且持续获取定位信息(全局设置一次)(单页面监听定位改变)(不采用定时器)

本篇文章实现了uniapp 微信小程序实时获取定位信息,小程序打开即可持续获取定位信息, 位置更新也会触发相关自定义事件 优点 只设置一次不采用定时器的方式无需多个页面调用单独页面若想获取当前位置是否变化 可单独设置监听,并调用不同逻辑事件 原理: 采用uniapp推出的: un…

数学建模学习(7):Matlab绘图

一、二维图像绘制 1.绘制曲线图 最基础的二维图形绘制方法&#xff1a;plot -plot命令自动打开一个图形窗口Figure&#xff1b; 用直线连接相邻两数据点来绘制图形 -根据图形坐标大小自动缩扩坐标轴&#xff0c;将数据标尺及单位标注自动加到两个坐标轴上&#xff0c;可自定…

亚马逊云科技HPC解决方案,帮助浙江大学实现成本和科研任务的双丰收

浙江大学土壤学科是朱祖祥院士等几代土壤科学家共同创建的A国家重点学科&#xff0c;整体实力雄厚&#xff0c;优势特色明显&#xff0c;总体水平居国内前列。在亚马逊云科技科研创新支持计划&#xff08;Amazon Web Services Cloud Credits for Research&#xff09;的多次支持…

yolov8系列[五]-项目实战-yolov8模型无人机检测

yolov8系列[五]-项目实战-yolov8模型无人机检测 项目介绍项目展示功能简介代码结构如何启动 开发者模式1. 安装依赖环境2. 启动程序 源代码下载其他 项目介绍 无人机识别项目,无人机搭载nvidia jetson边缘计算板子,进行实时识别。使用yolov8算法&#xff0c;训练了识别无人机的…