最近在尝试用PUT方法的请求时一直产生400,415,500错误,弄了半天(真的是半天),尝试了各种办法,现在终于解决了,为了防止忘记,在此记录下

下面是一步步解决的步骤。(还有许多我略过了)如果只想看结果滑到底即可。

一开始遇到的是400错误,前端是这样写的

  $.ajax({
type: "POST", // 这里必须写POST
url: "/team/" + teamId,
data: $("#myForm").serialize() + "&_method=PUT",
dataType: "json",
success: function (vo) {
if (vo.code === 200) {
window.location.href = "/pages/team/list.html?pageNum=" + pageNum + "&pageSize=" + pageSize;
} else {
alert("更新失败!" + vo.msg);
}
}
});

我先在后台 TeamController 中对应的方法上打断点

  @ResponseBody
@RequestMapping(value = "team/{id}", method = RequestMethod.PUT)
public ResultVO<?> update(@PathVariable Integer id, Team team) {
team.setTeamId(id); // --------------------- 在这一行打断点
if (id != null && teamService.update(team)) {
return new ResultVO<>();
}
return new ResultVO<>("球队ID 不存在!", 500);
}

发现根本没有走到这里。

于是我就检查是否是 HiddenHttpMethodFilter 没有配置,然而 web.xml 写的好好的

<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

然后我按Ctrl点进 HiddenHttpMethodFilter 里,在里面打断点

  public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM; @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); // ---- (1) ----- //
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
} filterChain.doFilter(requestToUse, response);
}

发现它有走到这里, 但是走到 (1)这一行的时候, paramValue 没有取到值,也就是说 request 没有 _method 的值,可是我前端有写啊!折磨了好久,把 target 文件夹删了重开,paramValue 竟然就能取到值了!?离谱。

但是问题没有解决,依然还是400错误。

我又尝试把 _method=PUT 删掉,用 POST 请求,这样就可以正常访问到。但是这不是我要的结果,POST 请求已经被其他方法占用了。

一番百度,好几人说添加一行 contentType:"application/json" ,于是我就添加一行

  $.ajax({
type: "POST", // 这里必须写POST
url: "/team/" + teamId,
data: $("#myForm").serialize() + "&_method=PUT",
dataType: "json",
contentType: "multipart/form-data", // 添加了这一行
success: function (vo) {
if (vo.code === 200) {
window.location.href = "/pages/team/list.html?pageNum=" + pageNum + "&pageSize=" + pageSize;
} else {
alert("更新失败!" + vo.msg);
}
}
});

这回不是400了,变成了415错误。害,继续搞呗。

继续百度,有人说后台把 Team 对象改成一个map集合,像这样 : @RequestBody Map<String, String> map ,不出意料,改了之后没有任何作用。

我尝试把 type 由 “POST” 改成 “PUT” ,像这样


  $.ajax({
type: "PUT",
url: "/team/" + teamId,
data: $("#myForm").serialize(),
dataType: "json",
// contentType: "multipart/form-data",
success: function (vo) {
if (vo.code === 200) {
window.location.href = "/pages/team/list.html?pageNum=" + pageNum + "&pageSize=" + pageSize;
} else {
alert("更新失败!" + vo.msg);
}
}
});

这样后台只取到了 id, Team 里的信息没有取到。

我又怀疑是版本的问题。我将 target 清除,改成使用 maven 的 tomcat 插件启动(之前是用 tomcat 9.0.52),插件是 7 的版本。然而,很不幸,问题还是没有解决(我要吐槽一下这个tomcat插件,连页面都进不去,用下载的tomcat 9 就没问题)。

后来看到一篇说 JSON 的属性也要加上双引号 像这样 { “aaa”: “bbb” },而不是 { aaa: "bbb" },我就想,把 data 换成 JSON 格式试试,竟然就真的可以了!太奇怪了吧。

  $.ajax({
type: "POST", // 这里必须写POST
url: "/team/" + teamId,
data: {
"teamId": $teamId.val(),
"teamName": $teamName.val(),
"chineseName": $chineseName.val(),
"coach": $coach.val(),
"stadium": $stadium.val(),
"location": $location.val(),
"createTime": $createTime.val(),
"area": $area.val(),
"_method": "PUT" // 不要忘记写这一行,将来能把 POST 改成 PUT
},
dataType: "json",
// contentType: "multipart/form-data",
success: function (vo) {
if (vo.code === 200) {
window.location.href = "/pages/team/list.html?pageNum=" + pageNum + "&pageSize=" + pageSize;
} else {
alert("更新失败!" + vo.msg);
}
}
});

然而事情还没完,我把前端改成原先的模样,他竟然又可以了!看来不是前端的问题。那究竟是哪里的问题呢?首先排除是target的问题,因为前面删掉重新生成过了。应该是我哪里改对了又忘了。。。

后来,第二天,我又在另一个模块遇到了400错误。这回我把 ajax 的 data 改成 JSON 格式也无济于事了,之前的各种办法试了也没用,就卡死在这里了。

又过了一天,我想再看看是什么原因。既然一个可以用,另一个不可以,那对比一下两者之间有什么不同不就行了吗。首先前端的 ajax 都是一样的,检查 Controller,注解也都一样,没有缺失什么。

我又把目光转向了 pojo 类:

 // 这个是可以用的
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime; // 这个会报 400 错误
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;

两个 pojo 类都有 Date 类型的属性,但是其中一个少了@DateTimeFormat(pattern = "yyyy-MM-dd")注解。马上安排,我加上注解之后,果然可以正常运行了。

由此可见,@DateTimeFormat(pattern = "yyyy-MM-dd")注解是将浏览器发送到后台的数据进行打包的,如果没有的话在接受数据时就会发生问题。

而@JsonFormat(pattern = "yyyy-MM-dd")是将后台要发送给前端的数据进行打包的,如果没有这个注解前端显示就会有问题。

SSM PUT请求导致的400,415,500问题的更多相关文章

  1. 网络请求返回HTTP状态码(404,400,500)

    HTTP状态码(HTTP Status Code) 一些常见的状态码为: - 服务器成功返回网页 - 请求的网页不存在 - 服务不可用 所有状态解释: 1xx(临时响应) 表示临时响应并需要请求者继续 ...

  2. 解决ajax请求(SpringMVC后台)响应415/400/405错误

    解决ajax请求(SpringMVC后台)响应415/400/405错误 后端代码 bean public class user { private String username; private ...

  3. HTTP状态码100、200、300、400、500、600的含义

    1xx (临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 100 (继续) 请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101 (切换协议) 请 ...

  4. HTTP状态码,400,404,500,503

    HTTP状态码(HTTP Status Code) 一些常见的状态码为: 200 - 服务器成功返回网页 400 服务器不理解请求的语法 404 - 请求的网页不存在 503 - 服务不可用 所有状态 ...

  5. HTTP常见状态码(404、400、500)等错误

    一些常见的状态码为: 200 - 服务器成功返回网页 404 - 请求的网页不存在 503 - 服务不可用 详细分解: 1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明 ...

  6. 关于web资金系统提现安全保护,防止极快的重复并发请求导致重复提现的解决思路

    关于WEB金融系统中的提现安全问题很多人没有深入思想,导致有漏洞,常常会遇到有些人遇到被攻击到导资金损失的麻烦,     其实要彻底解决重复并发请求 导致重复提现问题,是需要花点心思的,并没有看起来的 ...

  7. Asp.net并发请求导致的数据重复插入问题

    前段时间工作中,有客户反应了系统中某类待办重复出现两次的情况.我核实了数据之后,分析认为是并发请求下导致的数据不一致性问题,并做了重现.其实这并不是一个需要频繁调用的功能,但是客户连续点击了两次,导致 ...

  8. java异常处理及400,404,500错误处理

        java代码中经常碰到各种需要处理异常的时候,比如什么IOException  SQLException  NullPointException等等,在开发web项目中,遇到异常,我现在做的就 ...

  9. http statusCode(状态码) 200、300、400、500序列

    201-206都表示服务器成功处理了请求的状态代码,说明网页可以正常访问.        200(成功)  服务器已成功处理了请求.通常,这表示服务器提供了请求的网页.        201(已创建) ...

  10. http statusCode(状态码) 200、300、400、500序列详解

    201-206都表示服务器成功处理了请求的状态代码,说明网页可以正常访问.200(成功) 服务器已成功处理了请求.通常,这表示服务器提供了请求的网页.201(已创建) 请求成功且服务器已创建了新的资源 ...

随机推荐

  1. gson TypeAdapter 和FieldNamingStrategy,SerializedName实现属性名称的设置别名

    gson TypeAdapter 和FieldNamingStrategy,SerializedName实现属性名称的设置别名 package com.example.core.mydemo.Type ...

  2. UVM reg model 常见问题记录

    1.仿真log中报出大量的"include_coverage not located, did you mean ***"? (1) user在构建register model或者 ...

  3. Oversampling Techniques

    ADC Operation Improving ADC Resolution 总结 根据奈奎斯特采样定理,Fsample >= 2 * Fsignal 在频域中,过采样能够降低白噪声功率谱密度 ...

  4. 解决每次centos7执行java --version git --version等命令时都要重新source /etc/profile后才能执行,否则找不到命令-转载

      linux mint 我们通常将环境变量设置在/etc/profile这个文件中,这个文件是全局的. /etc/profile:在登录时,操作系 统定制用户环境时使用的第一个文件 ,此文件为系统的 ...

  5. unity笔记001

    熟悉场景和物体的基本操作,q移动场景,e旋转物体,放大缩小,V键顶点吸附,相比快捷键,还是喜欢用xyz参数控制

  6. K8s高可用集群部署(四)

    k8s官网高可用部署参考:https://kubernetes.io/docs/setup/independent/high-availability/                 目录 一 ,k ...

  7. ABAP 选择屏幕内的组件以及使用

    选择屏幕组件 主要记录了ABAP编程中选择屏幕常用的组件 选择框 范围选择框 radio单选 check选择 单行展现 配合radio和check使用较多 下拉框 自定义下拉框 按钮 文件框 文字帮助 ...

  8. 记SpringBoot中 Consider defining a bean of type 'com.xxx.classname' in your configuration 错误的解决办法

    一.背景 笔者项目中.有两个子模块代码.需要分别在不同的包名中运行,假设一个包名为 cn.com.a,另一个包名为cn.com.b.由于启动类只加了@SpringBootApplication注解,所 ...

  9. C/C++:printf 函数格式化输出,用法详细记录

    printf ( print format )函数是接触C/C++之后接触的第一个函数,它的功能除了输出hello world外,更重要的是进行格式化输出,比如输出整数的%d,输出小数的%f,%lf ...

  10. mysql使用保留字导致该列查不出来(mysql版本问题)

    mysql版本是 问题: 如图这边groups是sql的保留字此时这样查询是查不出来的,并会报错语法错误.但是在5.几的mysql版本中这行sql就没有问题. 解决方法: 在groups列上加上'gr ...