Spring Boot升级后PATCH/DELETE请求被错误识别为POST请求引发业务异常
你遇到的这个问题我之前也帮别的开发者排查过,核心原因大概率是Spring Boot版本升级后,HTTP方法转换的默认配置变了,结合HTML表单的限制导致的,咱们一步步捋清楚:
首先,先明确HTML表单的局限性
HTML原生表单只支持GET和POST两种请求方法,咱们平时用的PATCH/DELETE其实是通过POST请求+隐藏域模拟的——也就是在表单里加一个<input type="hidden" name="_method" value="PATCH" />(DELETE同理),然后靠Spring的HiddenHttpMethodFilter把这个POST请求转换成对应的PATCH/DELETE方法。
问题出在Spring Boot的默认配置变更
在你升级的Spring Boot 2.2版本及以后,官方把HiddenHttpMethodFilter的默认启用状态从true改成了false!也就是说,升级后这个负责转换请求方法的过滤器默认不工作了,你的表单提交的POST请求带着_method=PATCH参数,但Spring根本没处理,还是把它当成普通POST请求,自然就路由到了标注RequestMethod.POST的create()方法,而不是你期望的update()方法。
解决方案很简单,两步搞定
确保页面表单的模拟配置正确
检查你的Edit页面表单,确认:- 表单的
method属性是post - 表单里有一个隐藏域:
<input type="hidden" name="_method" value="PATCH" />(如果是DELETE请求就把value改成DELETE)
- 表单的
开启Spring Boot的HiddenHttpMethodFilter
在你的application.properties(或者application.yml)里添加一行配置:spring.mvc.hiddenmethod.filter.enabled=true这样Spring就会重新处理
_method参数,把POST请求转换成对应的PATCH/DELETE方法。
额外检查点
你代码里的GetMethodConvertingFilter只对DispatcherType.FORWARD类型的请求生效,把请求方法强制改成GET,这个过滤器本身不会影响直接提交的表单请求(表单提交是REQUEST类型),所以暂时不用怀疑它。不过如果之后遇到转发场景的问题,可以再回头看它的配置。
另外,你可以在控制器的方法里加一行日志或者打印语句,确认请求的实际方法和_method参数:
@RequestMapping(value = "/create", method = RequestMethod.POST) public String create(HttpServletRequest request) { System.out.println("实际请求方法:" + request.getMethod()); System.out.println("_method参数值:" + request.getParameter("_method")); // 原有逻辑 }
这样能更直观地确认问题是否解决。
备注:内容来源于stack exchange,提问作者MustyProgrammer

