【问题标题】:POST JSON fails with 415 Unsupported media type, Spring 3 mvcPOST JSON 失败,出现 415 Unsupported media type, Spring 3 mvc
【发布时间】:2012-07-14 14:14:25
【问题描述】:

我正在尝试向 servlet 发送 POST 请求。请求是通过 jQuery 以这种方式发送的:

var productCategory = new Object();
productCategory.idProductCategory = 1;
productCategory.description = "Descrizione2";
newCategory(productCategory);

newCategory 在哪里

function newCategory(productCategory)
{
  $.postJSON("ajax/newproductcategory", productCategory, function(
      idProductCategory)
  {
    console.debug("Inserted: " + idProductCategory);
  });
}

而 postJSON 是

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

使用 firebug 我看到 JSON 发送正确:

{"idProductCategory":1,"description":"Descrizione2"}

但我得到 415 Unsupported media type。 Spring mvc 控制器有签名

    @RequestMapping(value = "/ajax/newproductcategory", method = RequestMethod.POST)
public @ResponseBody
Integer newProductCategory(HttpServletRequest request,
        @RequestBody ProductCategory productCategory)

前几天有效,现在无效。如果需要,我会显示更多代码。 谢谢

【问题讨论】:

  • 从前几天你有什么变化?另外,var productCategory = { idProductCategory: 1, description: "Descrizione2" }; 不是更简洁更易于阅读吗?您需要告诉 Spring 专门接受application/json 吗?换句话说,它是否期望数据以某种形式出现?
  • 自从我在这个项目的其他部分工作以来,我做了很多事情,今天我发现了这个回归。在这部分我没有改变任何东西。是的,我必须使用这种方式,因为我从表单中获取输入。
  • 不,您不是,您是从 JSON Ajax 帖子中获取的,这与表单编码数据不同。
  • 您确定 Jackson 在您的 CLASSPATH 中仍然可用吗?
  • 如果你发送 text/json 而不是 application/json 你会得到同样的错误

标签: ajax json spring post http-status-code-415


【解决方案1】:

我以前使用 Spring @ResponseBody 发生过这种情况,这是因为没有随请求发送的接受标头。使用 jQuery 设置 Accept 标头可能会很痛苦,但这对我有用 source

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    headers: { 
        'Accept': 'application/json',
        'Content-Type': 'application/json' 
    },
    'type': 'POST',
    'url': url,
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

@RequestBody 使用 Content-Type 标头来确定请求中从客户端发送的数据的格式。 @ResponseBody 使用接受标头来确定在响应中将数据发送回客户端的格式。这就是为什么你需要两个标题。

【讨论】:

  • 标头:{...} 和 JSON.stringify(...) 总是让我失望。
  • 不知道为什么没有更多的记录。这个问题让我浪费了很多时间。非常感谢!
  • 我预计 Spring 默认支持表单数据,但事实并非如此。所以,感谢(现在相当旧的)解决方案。
  • 我是使用邮递员发出 put 请求的,只是添加了 content-type: ''application/json"。谢谢
【解决方案2】:

将内容类型添加到请求中作为application/json 解决了问题

【讨论】:

    【解决方案3】:

    我遇到了类似的问题,但发现问题是我忽略了为使用 @RequestBody 注释的 DTO 提供默认构造函数。

    【讨论】:

    • 同样的事情发生在我身上。我有 2 个同名方法,得到 415。谢谢!
    【解决方案4】:

    我遇到了类似的问题,我就是这样解决的,

    问题是由于从 JSON 到 Java 的转换过程,需要有正确的运行时 jackson 库才能正确进行转换。

    添加以下 jars(通过依赖或通过下载并添加到类路径。

    <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
    </dependency>
    

    这应该可以解决问题。

    完整代码:

    function() {
      $.ajax({
        type: "POST",
        url: "saveUserDetails.do",
        data: JSON.stringify({
          name: "Gerry",
          ity: "Sydney"
        }),
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        success: function(data) {
          if (data.status == 'OK')
            alert('Person has been added');
          else
            alert('Failed adding person: ' + data.status + ', ' + data.errorMessage);
    }
    

    控制器签名如下所示:

    @RequestMapping(value = "/saveUserDetails.do", method = RequestMethod.POST)
    public @ResponseBody Person addPerson( @RequestBody final  Person person) {
    

    希望对你有帮助

    【讨论】:

    • 只需要jackson-databind
    【解决方案5】:

    我相信我遇到了同样的问题。经过无数小时与 JSON、JavaScript 和服务器的斗争,我找到了罪魁祸首:在我的例子中,我在 DTO 中有一个 Date 对象,这个 Date 对象被转换为一个字符串,因此我们可以在视图中显示它格式:HH:mm。

    当返回 JSON 信息时,这个 Date String 对象必须被转换回一个完整的 Date 对象,因此我们还需要一个方法来在 DTO 中设置它。最大的问题是 DTO 中不能有 2 个具有相同名称(重载)的方法,即使它们具有不同类型的参数(字符串与日期),因为这也会给您 415 Unsupported Media type 错误。

    这是我的控制器方法

      @RequestMapping(value = "/alarmdownload/update", produces = "application/json", method = RequestMethod.POST)
      public @ResponseBody
      StatusResponse update(@RequestBody AlarmDownloadDTO[] rowList) {
        System.out.println("hola");
        return new StatusResponse();
      }
    

    这是我的 DTO 示例(不包括 id get/set 和 preAlarm get 方法以缩短代码):

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class AlarmDownloadDTO implements Serializable {
    
      private static final SimpleDateFormat formatHHmm = new SimpleDateFormat("HH:mm");
    
      private String id;
      private Date preAlarm;
    
      public void setPreAlarm(Date date) { 
        this.preAlarm == date;
      }
      public void setPreAlarm(String date) {    
        try {
          this.preAlarm = formatHHmm.parse(date);
        } catch (ParseException e) {
          this.preAlarm = null;
        } catch (NullPointerException e){
          this.preAlarm = null;
        }
      }
    }
    

    要使一切正常,您需要删除带有 Date 类型参数的方法。这个错误非常令人沮丧。希望这可以节省一些人的调试时间。

    【讨论】:

    • 谢谢 - 或者您可以重命名其中一个二传手。我在一个 bean 中同时拥有 public void setParameters(List&lt;Parameter&gt; parameters)public void setParameters(Parameter... parameters) 方法,将后者更改为 addParameters 为我解决了这个问题。
    • body 是 this.preAlarm == date 而不是 this.preAlarm = date 不是问题吗?
    【解决方案6】:

    我在将 spring boot 与 spring mvc 集成时遇到了这个问题。我通过添加这些依赖项来解决它。

    <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
    </dependency>
    

    【讨论】:

      【解决方案7】:

      一个小提示 - 在开发 Web 应用程序时偶然发现了同样的错误。通过使用 Firefox Poster 来玩弄该服务,我们发现的错误是 Json 中的字段和值都应该用双引号引起来。比如……

      [ {"idProductCategory" : "1" , "description":"Descrizione1"}, 
        {"idProductCategory" : "2" , "description":"Descrizione2"} ]
      

      在我们的例子中,我们通过 javascript 填充 json,据我所知,在处理单引号/双引号时可能会有点混乱。

      之前在这篇文章和其他帖子中所说的内容,例如包含“Accept”和“Content-Type”标题,也适用。

      希望对你有所帮助。

      【讨论】:

        【解决方案8】:

        我设法让它发挥作用。告诉我,以防我错了。 我只使用了一种方法来序列化/反序列化:我删除了所有关于此的注释(@JSONSerialize@JSONDeserialize)并在CustomObjectMapper 类中注册了序列化器和反序列化器。 我没有找到解释这种行为的文章,但我以这种方式解决了。希望有用。

        【讨论】:

        • 对我也是一样!任何解释为什么会发生?
        • 你能详细解释一下你的方法吗?
        【解决方案9】:

        我遇到了同样的问题。我必须按照以下步骤解决问题:

        1.确保您具有以下依赖项:

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>${jackson-version}</version> // 2.4.3
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson-version}</version> // 2.4.3
            </dependency>
        

        2。创建以下过滤器:

            public class CORSFilter extends OncePerRequestFilter {
        
                @Override
                protected void doFilterInternal(HttpServletRequest request,
                                                HttpServletResponse response, FilterChain filterChain)
                        throws ServletException, IOException {
        
                    String origin = request.getHeader("origin");
                    origin = (origin == null || origin.equals("")) ? "null" : origin;
                    response.addHeader("Access-Control-Allow-Origin", origin);
                    response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, DELETE, OPTIONS");
                    response.addHeader("Access-Control-Allow-Credentials", "true");
                    response.addHeader("Access-Control-Allow-Headers",
                            "Authorization, origin, content-type, accept, x-requested-with");
        
                    filterChain.doFilter(request, response);
                }
            }
        

        3.对 web.xml 中的请求应用上述过滤器

            <filter>
                <filter-name>corsFilter</filter-name>
                <filter-class>com.your.package.CORSFilter</filter-class>
            </filter>
            <filter-mapping>
                <filter-name>corsFilter</filter-name>
                <url-pattern>/*</url-pattern>
            </filter-mapping>
        

        我希望这对某人有用。

        【讨论】:

        • jackson-corejackson-databinddependency,所以不需要直接添加。
        • 为什么要添加CORS过滤器?
        【解决方案10】:

        spring boot + spring mvn

        有问题

        @PostMapping("/addDonation")
        public String addDonation(@RequestBody DonatorDTO donatorDTO) {
        

        有解决办法

        @RequestMapping(value = "/addDonation", method = RequestMethod.POST)
        @ResponseBody
        public GenericResponse addDonation(final DonatorDTO donatorDTO, final HttpServletRequest request){
        

        【讨论】:

          【解决方案11】:

          我通过将 jackson-json 数据绑定添加到我的 pom 解决了这个问题。

          <dependency>
                  <groupId>com.fasterxml.jackson.core</groupId>
                  <artifactId>jackson-databind</artifactId>
                  <version>2.6.3</version>
          </dependency>
          

          【讨论】:

            【解决方案12】:

            在你的模型类中添加一个 json 属性注解,还有一个默认构造函数

            @JsonProperty("user_name")
            private String userName;
            
            @JsonProperty("first_name")
            private String firstName;
            
            @JsonProperty("last_name")
            private String lastName;
            

            【讨论】:

              【解决方案13】:

              我有同样的问题。添加

              <mvc:annotation-driven />
              <mvc:default-servlet-handler />
              

              到spring-xml解决了

              【讨论】:

                【解决方案14】:

                除了设置 Accept 和 Content-Type 标头并确保它们与您的控制器方法的消耗/生成设置相匹配之外,您可能还需要查看 JSON 结构并确保编组和处理没有问题解组。在我的情况下,内容类型还可以,但是将 JSON 请求映射到我的请求/响应模型时存在问题。通常,控制器应该返回 400 错误而不是 415 错误,但在我的情况下,错误代码是 415。我通过添加一个测试类来调试问题,其中我使用 ObjectMapper 将我的 JSON 读入请求模型对象。 ObjectMapper 因请求而窒息,并给了我有用的错误,帮助我修复了模型类定义。

                【讨论】:

                  【解决方案15】:

                  1.a.在 applicationContext-mvc.xml 中添加以下内容

                  xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc

                  1. 添加杰克逊库

                  【讨论】:

                    猜你喜欢
                    • 2021-07-16
                    • 1970-01-01
                    • 2020-12-16
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多