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使用minio的基本操作

Java使用minio的基本操作 导入jar包 <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>7.0.2</version> </dependency>public static void main(String[] args) {try{MinioClient minioClie…

吃透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;抽象表…

android 浏览器 多窗口显示,Android浏览器图形侧多窗口方案

Android平台浏览器当前多窗口方案为多个浏览器子窗口公用一个图形buffer&#xff0c;窗口的z序和显示控制由浏览器进程维护&#xff0c;图形侧只能看到一个窗口。该方案能基本实现浏览器多窗口的大部分需求。但无法实现linux机顶盒中存在的部分窗口交叉的业务场景&#xff0c;即…

response.reset() 与response.resetbuffer使用场景

getResponse的getWriter()方法 getResponse的getWriter()方法连续两次输出流到页面的时候&#xff0c;第二次的流会包括第一次的流&#xff0c;所以可以使用response.reset或者resetBuffer的方法。 reset(): Clears any data that exists in the buffer as well as the statu…

android listview asynctask,关于android:ListView + ArrayList + AsyncTask

本问题已经有最佳答案&#xff0c;请猛点这里访问。我的想法是使用AsynTask下载数据集并存储在arrayList中。 我已经检查并运行良好。在onPostExecute方法中&#xff0c;我调用一个函数来更新listView&#xff0c;然后加载存储在ArrayList中的数据。码&#xff1a;protected vo…

ServletResponse reset()方法慎用

reset()用于重置,但是在重置的时候也会清空相关数据,例如session存的信息。

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;然后根据…

android imageview 设置网络图片,ImageView加载网络图片

android网络加载图片框架Android-Universal-Image-Loader功能非常强大&#xff0c;其开源地址https://github.com/nostra13/Android-Universal-Image-Loader&#xff0c;讲解非常地详细&#xff0c;今天我要贴下工作中用到的利用这个框架加载网络图片并在ImageView控件中显示出…

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;可以打印出日志信息所属的类。 …

signature=f0dd2033ed5bb3cdb94f9136381f7750,Lesson 8: Signature Assignment

摘要&#xff1a;This unit will focus on the Civil Rights Era in the 1960s. Students will learn what the Civil Rights Movement was and how it changed the United States. By learning about the pivotal leaders of the movement, students will build their underst…

LoggerFactory.getLogger的用法

Logger类下有多个不同的error方法&#xff0c;根据传入参数的个数及类型的不同&#xff0c;自动选择不同的重载方法。 使用&#xff0c;只打印异常&#xff0c;不打印堆栈信息 private static final Logger logger LoggerFactory.getLogger(LoggerTest.class);Testpublic voi…

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;而调用端只需要做的…

正则匹配承兑的html,正则匹配闭合HTML标签(支持嵌套)

原标题&#xff1a;正则匹配闭合HTML标签(支持嵌套)任何复杂的正则表达式都是由简单的子表达式组成的&#xff0c;要想写出复杂的正则来&#xff0c;一方面需要有化繁为简的功底&#xff0c;另外一方面&#xff0c;我们需要从正则引擎的角度去思考问题。关于正则引擎的原理&…