springboot源码分析: 请求方式+请求映射原理+获取参数原理

注解相关

@AliasFor:.在同个注解中为同一个功能定义两个名称不一样的属性,那么这两个属性彼此互为别名
@RequestMapping注解里面的代码

	@AliasFor("path")String[] value() default {};@AliasFor("value")String[] path() default {};

@GetMapping @PostMapping @DeleteMapping等都是@RequestMapping修饰

@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {}

MVC处理流程
在这里插入图片描述

一:springmvc请求方式的选择

如果是用的表单提交, 不能支持delete那些方式, 需要开启一下过滤器。但是现在前后端分离, 直接就可以发delete那些方式。
WebMvcAutoConfiguration中, 配置了一个命令隐藏方法过滤器
在这里插入图片描述
一直进去可以看见这里默认的参数是_method
在这里插入图片描述
回到WebMvcAutoConfiguration中, 我们看见, 如果默认过滤器是false, 未开启, 我们去配置文件中开启
在这里插入图片描述

配置
spring:mvc:hiddenmethod:filter:enabled: true
前端<form action="/test" method="post"><input type="hidden" name="_method" value="DELETE"><input type="submit" value="提交">
</form>
后端@ResponseBody@RequestMapping(value = "/test", method = RequestMethod.DELETE)public String getTest(){return "DELETE";}
结果就是成功请求到, 如果没有开启, 就会失败

现在我们来看一下请求过程

请求进来, 判断是不是post请求, 并且是否正常,如果是就进入if里面
进来后获取到this.methodParam里面的值, 点进去发现就是_method,
所以: 这里就是获取我们过程名字为_method的input标签里面的值
拿到以后会判断这个值是不是正常, 正常的话就变成大写,所有我们前端大写小写都可以
然后去判断ALLOWED_METHODS里面是不是包含这个值, 如果包含,就new一个HttpMethodRequestWrapper返回
HttpMethodRequestWrapper就是重写了ServletRequest,进行了包装

在这里插入图片描述
这里可以看见mvc支持这些请求
在这里插入图片描述
特别注意: 因为表单只能发post和get, 所有才会进入if里面, 如果是客户端工具, 直接发送delete就不用进去, 直接就用的requestToUse

自定义_method
在这里插入图片描述
这里给了我们方法, 我们只需要修改一下, 给他注入到容器里面就可以了。

@Configuration(proxyBeanMethods = false)//@Configuration(proxyBeanMethods = false),提高Spring启动速度
public class WebConfig {@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter hiddenHttpMethodFilter1 = new HiddenHttpMethodFilter();hiddenHttpMethodFilter1.setMethodParam("_myMethod");return hiddenHttpMethodFilter1;}
}

二:请求映射原理

所有请求都会来到中央处理器DispatcherServlet, 我们去里面找到doGet和doPost,在FrameworkServlet中, 我们找到了
在这里插入图片描述

再doGet里面processRequest再调用他本类里面的doService方法处理rqquest和response

这里的doService是一个抽象方法, 并没有实现, 所有一定在子类里面实现。
在中央处理器DispatcherServlet里面, doService被实现了
在这里插入图片描述
经过一系列的初始化过程, doService里面 调用了doDispatch(request, response);每个请求进来都会调用doDispatch方法, 这才是我们要研究的方法。

综上所述:经过系列的辗转反侧, 我们终于找到了最终处理request, response的方法, 就是doDispatch, 我们继续研究doDispatch方法

请求过来以后, 会把请求包装一下,然后判断是不是文件上传multipartRequestParsed请求, 默认是false.
在这里插入图片描述

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
判断是不是异步, 是的话就使用一个异步管理器。

再往下走:
在这里插入图片描述
走到核心这里, 这就是找到映射地址的关键: 这里调用本类的一个getHandler方法, 在这个方法里面找到映射地址
进入这个方法, 我们看见这里是一个for循环的方式来找寻找。
在这里插入图片描述
这里的handermappers一共有5个, 我们需要的就是第一个
在这里插入图片描述
在这里面我们找到了所有的映射地址, 包括系统给我们写的, 当然, 也有这次要找的。
在这里插入图片描述
在这里面就可以找到,这个映射地址的方法叫getTest, 在helloController这个类里面
在这里插入图片描述
在for循环的Mapping.getHander()方法里面, 调用了一个方法,在这个方法里面找到最终的结果
在这里插入图片描述
我们一直往下运行, 找到RequestMappingInfoHandlerMapping类, 这里面有一个方法处理了request请求
在这里插入图片描述
进入这个方法, 我们看见这里面找到了路径
在这里插入图片描述

但是路径可能相同, 但是请求方式不同,这里把路径和requst再进行处理
在这里插入图片描述
我们发现这里相同的路径找到了两个请求
在这里插入图片描述
然后又把这两个结果放到一个方法里面去找最佳匹配
在这里插入图片描述
经过这里的循环, 就找到了最终的结果
在这里插入图片描述

三:参数解析原理

走到了这一步
在这里插入图片描述

接着上面的, 拿到具体的方法以后, 我们就要去到一个适配器
在这里插入图片描述
进去后发现, 这里有4个处理器适配器

  1. 支持RequestMapping,(我们的controller都是这个)
  2. 支持函数式编程
    在这里插入图片描述
    这里返回的就是RequestMappingHandlerAdapter
    返回以后(中央处理器)我们继续往下走, 我们会走到一个核心方法,Actually invoke the handler.实际调用处理程序
    在这里插入图片描述
    进入这个方法, 我们会走到RequestMappingHandlerAdapter, 这里做一些真正的处理, 在这里,执行目标方法
    在这里插入图片描述
    在这个方法里面有一个参数解析器
    在这里插入图片描述
    参数解析器里面有这些,这里确定我们将要执行的目标方法的每一个参数的值是什么。我们平时写的@RequestParam,就在这里第一个处理的。
    在这里插入图片描述
    这里还有返回值处理器
    在这里插入图片描述

继续往下,处理请求的一个方法就在这里,
在这里插入图片描述
进去这个方法里面, 就会来到我们的controller
在这里插入图片描述
真真真执行目标方法ServletInvocableHandlerMethod类里面。
在这里插入图片描述
这里面再进去, 会到InvocableHandlerMethod, 这里面获取参数的值,代码如下

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {MethodParameter[] parameters = getMethodParameters();if (ObjectUtils.isEmpty(parameters)) {return EMPTY_ARGS;}Object[] args = new Object[parameters.length];for (int i = 0; i < parameters.length; i++) {MethodParameter parameter = parameters[i];parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] != null) {continue;}if (!this.resolvers.supportsParameter(parameter)) {throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));}try {args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);}catch (Exception ex) {// Leave stack trace for later, exception may actually be resolved and handled...if (logger.isDebugEnabled()) {String exMsg = ex.getMessage();if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {logger.debug(formatArgumentError(parameter, exMsg));}}throw ex;}}return args;}

总结:
请求进来以后会先去走过滤器拿到它是哪一种请求方式,
在这里插入图片描述

拿到以后走service方法去走一个请求转发,通过if else找到请求方式, 去调用doGet, doPost等方法。
在这里插入图片描述
在这里插入图片描述
然后就是上面的去寻找具体方法。

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

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

相关文章

android 或者vide的高度和宽度,关于Android中videoView.setVideoPath(“PATH”)的问题!!!急!!...

满意答案yfdsan31972015.06.03采纳率&#xff1a;52% 等级&#xff1a;9已帮助&#xff1a;364人path 是获取的路径&#xff0c;如果你把视频文件夹写在raw文件夹下 &#xff0c;/*** raw文件夹下的文件处理工具类** */public class RawFileUtils {private RawFileUtils( ){…

吃透Java IO:字节流、字符流、缓冲流

文章目录前言1 初识Java IO1.1 IO流分类1.2 案例实操2 IO流对象2.1 File类2.2 字节流2.3 字符流2.4 序列化3 IO流方法3.1 字节流方法3.2 字符流方法4 附加内容4.1 位、字节、字符4.2 IO流效率对比4.3 NIO前言 有人曾问fastjson的作者&#xff08;阿里技术专家高铁&#xff09;&…

android 侧滑删除功能,200行代码让你在Android中完美实现iOS版侧滑删除效果

使用几个月的IOS之后,发现IOS中侧滑删除俺就大家好&#xff0c;自己开始学习Android已经差不多半年了吧&#xff0c;前前后后看了不少的博客获益匪浅。渐渐的随着技术的提升&#xff0c;慢慢感觉网上其它的一些功能的实现又不是那么完美&#xff0c;今天就给大家带来一篇在Andr…

java IO体系的学习总结

1.Java Io流的概念&#xff0c;分类&#xff0c;类图。 1.1 Java Io流的概念 ? ? java的io是实现输入和输出的基础&#xff0c;可以方便的实现数据的输入和输出操作。在java中把不同的输入/输出源&#xff08;键盘&#xff0c;文件&#xff0c;网络连接等&#xff09;抽象表…

android10获取imei,Android 10 root用户获取imei

IMEI(International Mobile Equipment Identity)是国际移动设备识别码的缩写&#xff0c;由15-17位数字组成&#xff0c;与手机是一一对应的关系。无论刷机还是恢复出厂设置&#xff0c;该设备标识码都不会改变&#xff0c;所以在广告和流量统计等方面特别好用&#xff0c;备受…

JAVA基础之HttpServletResponse响应

JAVA基础之HttpServletResponse响应 用户在客户端输入网址&#xff08;虚拟路径&#xff09;时&#xff0c;开始发送一个HTTP请求&#xff08;请求行、请求头、请求体&#xff09;至服务器。服务器内的Tomcat引擎会解析请求的地址&#xff0c;去找XML文件&#xff0c;然后根据…

Logger之Logger.getLogger(CLass)

之前一直在使用System.out.println()来调试.但是用这种方式开发项目部署到生产环境,会因为众多的控制台输出降低应用的性能.这时候Log4J就成为可平衡开发和部署应用的利器了. 在项目中使用Log4J并不是一件困难的事情,简单粗暴的方式就是在每个类A中声明一个Logger私有属性 pri…

订阅号助手android,微信订阅号助手app

微信订阅号助手app属于微信官方推出的软件&#xff0c;可以把我们的手机当做公众号的平台&#xff0c;让你直接用手机来实现公众号的各种工作、互动内容&#xff0c;微信订阅号助手app不用担心使用一些第三方软件被封号了&#xff0c;非常实用可靠。【应用介绍】订阅号助手是一…

使用LoggerFactory.getLogger(xxx.class)方法在控制台打印日志信息

使用System.out.println()来调试.但是用这种方式开发项目部署到生产环境,会因为众多的控制台输出降低应用的性能.这时候Log4J就成为可平衡开发和部署应用的利器了. 使用指定的类XXX初始化日志对象&#xff0c;方便在日志输出的时候&#xff0c;可以打印出日志信息所属的类。 …

html自动增加vbs代码,vbs脚本病毒代码大全编步骤四个

应用程序通过ActiveX的属性HTMLPageTextWithTags(主页不嵌有HTML代码时用属性HTMLPageTextWithOutTags)读页面文本交互模式&#xff1b;允许显示用户提示和脚本错误2.ntlm.vbs***************ntlm.vbsby黑嘿黑***************dimwshsetwshCreateObject("WScript.Shell&quo…

java util logger slf4j_别再自己用LoggerFactory生成logger实例了,试试slf4j注解

背景 在项目开发中&#xff0c;记录日志是必做的一件事情。日志的实现有很多种&#xff1a;Logback&#xff0c;Log4j2&#xff0c;log4j&#xff0c;JAVA Util Logging等等。 而slf4j是一个适配层&#xff0c;由适配层决定使用哪一种日志系统&#xff0c;而调用端只需要做的…

日志框架介绍(SLF4J及其使用)

本文主要介绍 1.日志框架基本介绍及Spring Boot中默认使用框架(SLF4JLogBack); 2.SLF4J的使用 3.项目中日志框架统一问题 4.Spring Boot中如何实现日志框架统一问题(3的最佳实践) 1. 日志框架基本介绍 一般情况下搭建日志框架时&#xff0c;搭建 日志抽象层&#xff08;定…

jmeter生成html报告修改,Jmeter生成html报告(示例代码)

新的JMeter版本中引入了Dashboard Report&#xff0c;用于生成HTML页面格式图形化报告的扩展模块。注&#xff1a;本文用的是3.2版本。生成html报告一、检查.jtl文件&#xff0c;如果没有.jtl文件&#xff0c;运行如下命令&#xff1a;jmeter -n -t 天气api.jmx -l result.jtl …

SpringBoot使用Slf4j+Log4j2完成项目的日志记录

SpringBoot使用Slf4jLog4j完成项目的日志记录 前言 本示例采用SpringBoot项目使用SpringAOP记录日志&#xff0c;Slf4j作为日志门面&#xff0c;Log4j2作为日志实现实&#xff0c;实现开发中的日志记录. 部分效果展示 &#xff1a; 日志文件 : 日志信息 : 代码具体实现如下…

鸿蒙构架谁提供的,科普丨关于“鸿蒙”,不知道这些你都不好意思跟别人打招呼!...

鸿蒙的英文名是Harmony OS华为消费者业务CEO余承东8月9日正式发布鸿蒙系统&#xff0c;英文名是Harmony OS 。国家知识产权局商标局网站显示&#xff0c;华为已经申请注册“华为鸿蒙”商标&#xff0c;申请日期是2018年8月24日&#xff0c;注册公告日期是2019年5月14日。鸿蒙是…

springBoot Logging 日志详解

文章目录日志格式控制台输出彩色编码输出文件输出文件级别自定义日志配置Logback 扩展profile 指定 配置文件Environment 属性springBoot 日志使用Commons Logging作为抽象层&#xff0c;并将具体实现开放&#xff0c;支持Java Util Logging、Log4j2和Logback。loggers 默认配置…

计算机应用电子技术课程,中专计算机应用有什么课程

中专计算机应用有什么课程2020-10-29 16:40:11文/董玉莹计算机应用学习研究计算机应用于各个领域的理论、方法、技术和系统等&#xff0c;是计算机学科与其他学科相结合的边缘学科&#xff0c;是计算机学科的组成部分。计算机应用是对在社会活动中的如何参与和实施给予方针指导…

Spring Boot 配置日志输出等级

Spring boot 默认使用 logback作进行日志输出。 有两种方式一个是通过application.properties 配置文件的方式来配置。 另一种是通过logback.xml配置文件的方式进行配置。 首先要说的是:application.properties 和logback.xml这两个配置文件都是放在 src/main/resources 目录…

springboot如何使用log4j记录日志

文章目录导入依赖1、去掉slf4j的依赖2、引入log4j的依赖创建log4j.properties导入依赖 因为springboot的启动依赖会引入SLF4J的日志依赖&#xff0c;因此想要用log4j&#xff0c;就要先把slf4j的依赖去掉&#xff0c;然后再引入log4j的启动依赖。 1、去掉slf4j的依赖 网上有…

在SpringBoot中使用slf4j与logbak

本次开发环境为&#xff1a; 系统&#xff1a;Windows 10 JDK&#xff1a;1.8 开发工具&#xff1a;IntelliJ IDEA springboot框架&#xff1a;2.X.X 日志设置参考官方文档https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boo…