Java HTTP 状态 406。Spring MVC 4.0、jQuery、JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21235472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:31:53  来源:igfitidea点击:

HTTP Status 406. Spring MVC 4.0, jQuery, JSON

javajqueryjsonspringspring-mvc

提问by Shatranaft

I want to send JSON from my controller. I have the following configuration.

我想从我的控制器发送 JSON。我有以下配置。

spring-servlet.xml :

弹簧 servlet.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <mvc:annotation-driven/>

    <mvc:resources mapping="/resources/**" location="/resources/"/>
    <context:component-scan base-package="com.castle.controllers"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

.js :

.js :

function testAjax() {
    var data = {userName: "MyUsername", password:"Password"};
    $.ajax({
        url: 'ajax/test.htm',
        dataType : 'json',
        type : 'POST',
        contentType: "application/json",
        data: JSON.stringify(data),
        success: function(response){
            alert('Load was performed.');
        }
    });
}

UserTest.java:

用户测试.java:

public class UserTest {
    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

TestAjaxController.java :

TestAjaxController.java :

@Controller
@RequestMapping("/ajax")
public class TestAjaxController {

    @RequestMapping(method = RequestMethod.POST, value = "/test.htm")
    public @ResponseBody
    UserTest testAjaxRequest(@RequestBody UserTest user) {
        return user;
    }
}

pom.xml :

pom.xml :

    <dependency>
                <groupId>org.codehaus.Hymanson</groupId>
                <artifactId>Hymanson-mapper-asl</artifactId>
                <version>1.9.13</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.Hymanson</groupId>
                <artifactId>Hymanson-core-asl</artifactId>
                <version>1.9.13</version>
</dependency>

When i do this request, i get in my Controller JSON represented as UserTest object. But on return :

当我执行此请求时,我进入了表示为 UserTest 对象的控制器 JSON。但返回时:

HTTP Status 406 - The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.

HTTP 状态 406 - 此请求标识的资源只能生成具有根据请求“接受”标头不可接受的特征的响应。

What i'm doing wrong? I know, there is a lot of questions about such cases, but i can't fix it for 2 days...

我在做什么错?我知道,关于这种情况有很多问题,但我不能解决它2天......

UPDATEI Have found the solution!! It's only need to return an Object. Not a User object or something. But return Object;

更新我找到了解决方案!!只需要返回一个对象。不是 User 对象什么的。但 return Object;

 public @ResponseBody Object testAjaxRequest(@RequestBody UserTest user) {
        List<UserTest> list = new ArrayList<>();
        list.add(user);
        list.add(user);
        list.add(user);
        return list;

采纳答案by Sotirios Delimanolis

The main issue here is that the path "/test.htm"is going to use content negotiation first before checking the value of an Acceptheader. With an extension like *.htm, Spring will use a org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategyand resolve that the acceptable media type to return is text/htmlwhich does not match what MappingHymansonHttpMessageConverterproduces, ie. application/jsonand therefore a 406 is returned.

这里的主要问题是路径"/test.htm"将在检查Accept标头值之前首先使用内容协商。对于像 那样的扩展*.htm,Spring 将使用 aorg.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy并解决返回的可接受媒体类型text/htmlMappingHymansonHttpMessageConverter产生的内容不匹配的问题,即。application/json因此返回 406。

The simple solution is to change the path to something like /test, in which content negotiation based on the path won't resolve any content type for the response. Instead, a different ContentNegotiationStrategybased on headers will resolve the value of the Acceptheader.

简单的解决方案是将路径更改为类似/test,其中基于路径的内容协商不会解析响应的任何内容类型。相反,ContentNegotiationStrategy基于标头的不同将解析标头的值Accept

The complicated solution is to change the order of the ContentNegotiationStrategyobjects registered with the RequestResponseBodyMethodProcessorwhich handles your @ResponseBody.

复杂的解决方案是更改ContentNegotiationStrategy使用RequestResponseBodyMethodProcessor处理您的@ResponseBody.

回答by Marty

Make sure to use produces = "application/json" in your annotations.

确保在注释中使用 products = "application/json"。

回答by zjor

Adding these lines to context configuration solved the same issue for me:

将这些行添加到上下文配置中为我解决了同样的问题:

    <mvc:annotation-driven>
      <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingHymanson2HttpMessageConverter"/>
      </mvc:message-converters>
    </mvc:annotation-driven>

I used Spring 4.1.xand Hymanson 2.4.2

我用过Spring 4.1.xHymanson 2.4.2

回答by ramird23

I had the same problem in the end it was the version of org.codehaus.Hymanson 1.9.x, when I switched from 1.9.x Hymanson to 2.x (fasterxml) in my pom.xml

我最终遇到了同样的问题,它是 org.codehaus.Hymanson 1.9.x 的版本,当我在 pom.xml 中从 1.9.x Hymanson 切换到 2.x(fasterxml)时

<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-core</artifactId>
<version>2.2.3</version>
</dependency>

<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-databind</artifactId>
<version>2.2.3</version>
</dependency>

<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-annotations</artifactId>
<version>2.2.3</version>

</dependency>

also is necesary : <mvc:annotation-driven />

也有必要: <mvc:annotation-driven />

回答by jlaitio

I ran into this issue when upgrading Spring in a legacy project. The .htmlsuffix of the AJAX endpoints (which were trying to return JSON) were indeed forcibly made to try to produce HTML due to the suffix, and since the handlers were returning an object, the request ended in a 406 error since Spring couldn't figure out how to make HTML out of a plain Java object.

我在旧项目中升级 Spring 时遇到了这个问题。.htmlAJAX 端点的后缀(试图返回 JSON)确实由于后缀而被强制尝试生成 HTML,并且由于处理程序正在返回一个对象,因此请求以 406 错误结束,因为 Spring 无法计算了解如何从一个普通的 Java 对象中生成 HTML。

Instead of altering the endpoint suffixes, or doing a complete configuration of a custom ContentNegotiationStrategy, making this change was enough:

无需更改端点后缀或对 customContentNegotiationStrategy进行完整配置,只需进行此更改即可:

<mvc:annotation-driven />

changed to:

变成:

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
</bean>
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>