POST JSON 失败,出现 415 Unsupported media type, Spring 3 mvc

Posted

技术标签:

【中文标题】POST JSON 失败,出现 415 Unsupported media type, Spring 3 mvc【英文标题】:POST JSON fails with 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 你会得到同样的错误 【参考方案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-databind 的dependency,所以不需要直接添加。 为什么要添加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

    添加杰克逊库

【讨论】:

以上是关于POST JSON 失败,出现 415 Unsupported media type, Spring 3 mvc的主要内容,如果未能解决你的问题,请参考以下文章

Python Post 请求 - 通过 Outlook API 发送文件时出现 415 错误

前端ajax用post方式提交json数据给后端时,网络报错 415

错误 415 不支持的媒体类型:如果是 JSON,则 POST 未达到 REST,但如果是 XML,则可以

web前端 ajax请求报415/400错

将 POST 从 api 转发到另一个时出现错误代码 415

在SpringMVC中使用@RequestBody和@ResponseBody注解处理json时,报出HTTP Status 415的解决方案