POST JSON失败,出现415不支持的媒体类型,Spring 3 mvc


171

我正在尝试向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不支持的媒体类型。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明确接受吗?换句话说,它期望数据以某种形式出现吗?
戴夫牛顿

自从我在该项目的其他部分进行工作以来,发生了很多事情,今天我发现了这种回归。在这一部分,我没有做任何更改。是的,我必须使用这种方式,因为我从表单获取输入。
gc5

不,不是,您是从JSON Ajax发布中获得的,这与表单编码数据不同。
戴夫牛顿

1
您确定CLASSPATH上仍然可以使用Jackson吗?
Tomasz Nurkiewicz 2012年

1
如果您发送text / json而不是application / json
则会

Answers:


249

我以前在Spring @ResponseBody中发生过这种情况,这是因为没有随请求发送接收接受标头。使用jQuery设置Accept标头可能很麻烦,但这对我有用

$.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使用accept标头确定响应中将数据发送回客户端的格式。这就是为什么您需要两个标题。


1
标头:{...}和JSON.stringify(...)总是让我失望。
蒂姆·佩里

1
不知道为什么没有更多记载。这个问题使我浪费了很多时间。非常感谢你!
雨果·纳瓦·科普

我希望Spring默认情况下会支持表单数据,但事实并非如此。因此,感谢您的解决方案(现在已经很旧了)。
RiZKiT

我使用邮递员发出放置请求,只是添加了内容类型:“ application / json”。谢谢
Janatbek Sharsheyev

21

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


18

我有一个类似的问题,但发现问题是我忽略了为DTO提供默认构造函数,该构造函数带有@RequestBody注释。


同样的事情发生在我身上。我有2个同名方法,得到415。谢谢!
丹尼尔·维拉斯·布亚斯

12

我相信我也碰到了同样的问题。经过无数小时与JSON,JavaScript和Server的斗争,我发现了罪魁祸首:就我而言,我在DTO中有一个Date对象,该Date对象被转换为String,因此我们可以在视图中使用格式:HH:mm。

当发送回JSON信息时,必须将该Date String对象转换回完整的Date对象,因此我们还需要一种在DTO中进行设置的方法。但是,最大的问题是,即使DTO中的参数类型不同(字符串与日期),您也无法在DTO中使用两种具有相同名称的方法(重载),因为这也会给您415不支持的介质类型错误。

这是我的控制器方法

  @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 Methods):

@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<Parameter> parameters)public void setParameters(Parameter... parameters)方法,更改了后者即可addParameters为我解决问题。
Conor Svensson

这不是正文是this.preAlarm == date而不是this.preAlarm = date吗?
迈克尔(Michael)恢复莫妮卡·塞利奥(Monica Cellio)2016年

12

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

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

添加以下jar(通过依赖关系或通过下载并添加到classpath中)。

<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需要。
Alex78191

8

当我将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>

5

一个小注释-在开发Web应用程序时偶然发现了相同的错误。我们发现,通过使用Firefox Poster服务,发现的错误是Json中的字段和值都应该用双引号引起来。例如..

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

在我们的案例中,我们通过javascript填充了json,根据我所听到的信息,在处理单/双引号时可能会有些混乱。

本篇和其他文章中之前所说的内容(包括“ Accept”和“ Content-Type”标头)也适用。

希望能有所帮助。


3

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


发生在我身上!任何解释为什么会发生?
异想天开

您能详细解释一下您的方法吗?
Dipanshu Verma

1

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

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-core是的依赖jackson-databind,因此无需直接添加。
Alex78191

1
为什么必须添加CORS过滤器?
Alex78191

1

春季靴+春季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){

0

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

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

0

在您的模型类中添加一个json属性注释,也有一个默认的构造函数

@JsonProperty("user_name")
private String userName;

@JsonProperty("first_name")
private String firstName;

@JsonProperty("last_name")
private String lastName;

0

我遇到过同样的问题。加

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

到spring-xml解决了


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.