Spring Boot核心技术之Restful映射以及源码的分析

@RequestMapping(value = “/user”,method = RequestMethod.DELETE)

public String deleteUser(){

return “DELETE-张三”;

}

}

测试功能是否可用:

=========

观察效果:

Spring Boot核心技术之Restful映射以及源码的分析

可以看到最后两个请求都变成Get的请求了。由此我们可以引出来如下问题:

  1. 为什么不同的请求会出现相同的结果

  2. 怎么实现的才能完成我们的功能

后面的文章就是围绕上述的问题进行展开的。

解决问题:

=====

像之前的SpringMVC中的表单请求通过HiddenHttpMethodFilter实现的,这样我们查一下在SpringBoot中是怎么样的。

默认双击Shift键,输入WebMvcAutoConfiguration这个类

找到默认配置的过滤器:

@Bean

@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)

@ConditionalOnProperty(prefix = “spring.mvc.hiddenmethod.filter”, name = “enabled”, matchIfMissing = false)

public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {

return new OrderedHiddenHttpMethodFilter();

}

通过

OrderedHiddenHttpMethodFilter进入父类HiddenHttpMethodFilter:

在使用之前,我们需要将后两个的请求方式改写成post方式,并且需要在请求的时候传入一个 _method 方法(设置隐藏域);

<input value="REST-PUT提交"type=“submit” />

为什么要这样设置呢?我们到HiddenHttpMethodFilter中看下。

Spring Boot核心技术之Restful映射以及源码的分析

流程:

  1. 第一步保存了传入的请求

  2. 当该请求是post,并且请求没有异常,才能进入下面方法,不是Post请求将直接通过过滤器链放行。

  3. 获取请求中的参数(this.methodParam)

  4. DEFAULT_METHOD_PARAM = _method获得(作为真正的请求方式)

然后再测试,发现还是没有实现。

我再回到WebMvcConfiguration中:

@Bean

@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)

@ConditionalOnProperty(prefix = “spring.mvc.hiddenmethod.filter”, name = “enabled”, matchIfMissing = false)

public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {

return new OrderedHiddenHttpMethodFilter();

}

首先该类存在于容器中。

@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)

当容器中不存在 HiddenHttpMethodFilter 这个类的时候,下面内容开启(条件装配);

@ConditionalOnProperty(prefix = “spring.mvc.hiddenmethod.filter”, name = “enabled”, matchIfMissing = false)

表示:绑定的配置文件中:

spring.mvc.hiddenmethod.filter 名字为enable是默认不开启的(后续版本可能开启)。这样我们就找到了问题的所在。

所以我们需要在配置文件中配置(两种方法都可以)。

yaml:

spring:

mvc:

hiddenmethod:

filter:

enabled: true

properties:

spring.mvc.hiddenmethod.filter.enabled=true

重启项目:成功解决。

Spring Boot核心技术之Restful映射以及源码的分析

源码分析:

=====

主要是分析doFilterInternal:

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

throws ServletException, IOException {

HttpServletRequest requestToUse = request;

if (“POST”.equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {

String paramValue = request.getParameter(this.methodParam);

if (StringUtils.hasLength(paramValue)) {

String method = paramValue.toUpperCase(Locale.ENGLISH);

if (ALLOWED_METHODS.contains(method)) {

requestToUse = new HttpMethodRequestWrapper(request, method);

}

}

}

filterChain.doFilter(requestToUse, response);

}

  • 表单提交会带上 _method=PUT

  • 请求过来被HiddenHttpMethodFilter拦截

  • 请求是否正常,并且是POST

  • 获取到 _method 的值。

  • 兼容以下请求; PUT . DELETE . PATCH当方法走到上述代码11行时,进入ALLOWED_METHODS:private static final List<String> ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));如果请求里的参数在ALLOWED_METHODS存在,则执行下面代码。

  • **原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。**进入HttpMethodRequestWrapper对象中,向上找父类。本质还是HttpServletRequest由下面代码:private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper { private final String method; public HttpMethodRequestWrapper(HttpServletRequest request, String method) { super(request); this.method = method; } @Override public String getMethod() { return this.method; } }可知,接收到前面的请求封装为HttpMethodRequestWrapper返回。

  • 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。

部分补充:

由于源码中规则:将获得请求中的参数无条件的以英文格式转完成大写,所以前端的 value=“PUT” value的值大小写无影响。

String paramValue = request.getParameter(this.methodParam);

if (StringUtils.hasLength(paramValue)) {

String method = paramValue.toUpperCase(Locale.ENGLISH);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

对于面试,一定要有良好的心态,这位小伙伴面试美团的时候没有被前面阿里的面试影响到,发挥也很正常,也就能顺利拿下美团的offer。
小编还整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家,

在这里插入图片描述

在这里插入图片描述

最后感谢大家的支持,希望小编整理的资料能够帮助到大家!也祝愿大家都能够升职加薪!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
这位小伙伴面试美团的时候没有被前面阿里的面试影响到,发挥也很正常,也就能顺利拿下美团的offer。
小编还整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家,

[外链图片转存中…(img-8eQRH44Q-1713391388610)]

[外链图片转存中…(img-IIhhcTND-1713391388611)]

最后感谢大家的支持,希望小编整理的资料能够帮助到大家!也祝愿大家都能够升职加薪!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值