阅读 40

SSM PUT请求导致的400,415,500问题

最近在尝试用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 写的好好的



    httpMethodFilter
    org.springframework.web.filter.HiddenHttpMethodFilter


    httpMethodFilter
    /*


 然后我按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 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")是将后台要发送给前端的数据进行打包的,如果没有这个注解前端显示就会有问题。

原文:https://www.cnblogs.com/lgxblogs/p/15302894.html

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐