写点什么

Spring Boot 核心技术之 Rest 映射以及源码的分析,java 从入门到放弃

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:2006 字

    阅读完需:约 7 分钟

<body>


<form action="/user" method="get">


<input value="REST-GET 提交" type="submit" />


</form>


<form action="/user" method="post">


<input value="REST-POST 提交" type="submit" />


</form>


<form action="/user" method="delete">


<input value="REST-DELETE 提交" type="submit"/>


</form>


<form action="/user" method="put">


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


</form>


</body>


</html>


controller


package com.xbhong.Controller;


import org.springframework.stereotype.Controller;


import org.springframework.web.bind.annotation.*;


@RestController


public class myContro {


@RequestMapping(value = "/user",method = RequestMethod.GET)


public String getUser(){


return "GET-张三";


}


// @PostMapping("/user")


@RequestMapping(value = "/user",method = RequestMethod.POST)


publ


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ic String saveUser(){


return "POST-张三";


}


@RequestMapping(value = "/user",method = RequestMethod.PUT)


public String putUser(){


return "PUT-张三";


}


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


public String deleteUser(){


return "DELETE-张三";


}


}


测试功能是否可用:




观察效果:



可以看到最后两个请求都变成 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方法(设置隐藏域);


<form action="/user" method="post">


<input name="_method" type="hidden" value="DELETE"/>


<input value="REST-DELETE 提交" type="submit"/>


</form>


<form action="/user" method="post">


<input name="_method" type="hidden" value="PUT" />


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


</form>


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



流程:


  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


重启项目:成功解决。



源码分析:




主要是分析 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);


}

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
Spring Boot核心技术之Rest映射以及源码的分析,java从入门到放弃