目录
1、SpringBoot 集成SpringMVC 底层,表单提交REST风格请求,后端GET/POST/PUT/DELETE 四种方式处理细节
2、请求映射原理(只看RequestMappingHandlerMapping)
3、@MatrixVariable 接收请求的矩阵变量(不是传统意义的请求参数)
1、SpringBoot 集成SpringMVC 底层,表单提交REST风格请求,后端GET/POST/PUT/DELETE 四种方式处理细节
首先,前端表单只能发起 GET 和 POST 请求,但后端四种请求均可处理。那么前端如何发起DELETE 和 PUT 请求呢?
如下图所示,四种请求,在后端不作任何配置的情况下,同样是 /user 路径,get 和 post 能找到对应的后端请求,但是 delete 和 put 却都跑到了 后端的 get 请求里面
我们看一下SpringBoot 底层如何处理的请求
我们找到 WebMvcAutoConfiguration 下的 Http方法过滤器
(注释:SpringBoot 底层关于SpringMVC 的配置基本在 WebMvcAutoConfiguration 这个类中可以找到)
我们发现,它已经默认给返回了一个过滤器,直接点进去 ,发现他继承了 HiddenHttpMethodFilter ,在 HiddenHttpMethodFilter 中我们发现真正过滤http方法的实现代码如下:
那么,依照上面的规则,我们只需要在表单请求中添加key 为 _method 的参数,既可以让表单请求到想要的后端方法了
修改过的表单代码如下:
再次请求delete 和 put ,发现还是不对,反而两个都跳转 post 里面了
先别着急,我们回过头再看下一开始 hiddenHttpMethodFilter 这个过滤器头上的注解
那好吧,我们在yaml中配置一下这个属性为true,再试
发现,这次可以了✅
2、请求映射原理(只看RequestMappingHandlerMapping)
我们再深入一下,看SpringBoot底层处理请求,如何准确找到要访问的路径
我们知道,所有请求来到后端都会经过DispacherServlet
先找到DispacherServlet :/org/springframework/spring-webmvc/5.3.6/spring-webmvc-5.3.6.jar!/org/springframework/web/servlet/DispatcherServlet.class
发现 doPost doGet 的实现,我们在 DispacherServlet 继承的 FrameworkServlet 中 找到了 doPost 的实现,而doPost又调用 processRequest()
继续进去processRequest 查看具体的实现代码,在DispacherServlet 中 找到了 doService 的实现代码
掠过一系列set初始化方法,继续进入doDispatch()
只看关键的一部,进入 this.getHandler(processedRequest)
实际发起一个/ user 的 GET 请求,第一行断点,我们看到handlerMappings 中有四个mapping
可以简单看到,第一个是关于controller 的mapping,第五个是欢迎页的mapping
这个getHandler方法逻辑就是,拿request 通过while循环,匹配到适合的那个handler,并且返回给你供你使用
3、@MatrixVariable 接收请求的矩阵变量(不是传统意义的请求参数)
场景举例:通常会有一些信息存储在Session中,sessionId通常会存储在Cookie中进行前后端传递,如果用户吧该网站的Cookie 设置为禁用,那么我们就无法获取Cookie 进而无法获取Session中的某些信息。这时就可以使用区别于表单传参的方式,使用矩阵变量传参方式进行前后端交互。
例如这样写
前端:
后端接收:
但是矩阵变量在SpringBoot自动配置文件中的 UrlPathHelp 中又是默认禁止的,我们需要手动开启矩阵变量功能
我们先看他是怎么禁用的,然后在去开启
找到WebMvcAutoConfiguration 中的 configurePathMatch 路径映射配置
倒数第三行代码中的UrlPathHelper 中有一个 removeSemicolonContent 类型为布尔的变量默认是 true,他的意思就是移除分号内容
这就说明但凡在一个后端采用SpringBoot框架构建的网站的健康的网址中加入分号的后缀,都会被默认过滤掉
正好我们矩阵变量的传递方式也是以分号间隔的方式坠在网址后面,同样会被 UrlPathHelper 默认过滤掉
解除默认过滤配置的封印需要自己新增配置类覆盖默认配置
两种方式:第一种:配置类实现 WebMvcConfigurer 中的 configurePathMatch方法,并设置 removeSemicolonContent 为 false
第二种:自己新增一个配置类,并在配置类中新增一个用@bean注解加持的方法,返回一个 removeSemicolonContent 为 false 的WebMvcConfigrer
两种方法如下图所示: