【问题标题】:HTTP Status 406. Spring MVC 4.0, jQuery, JSONHTTP 状态 406。Spring MVC 4.0、jQuery、JSON
【发布时间】:2014-02-09 17:01:55
【问题描述】:

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

spring-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:

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:

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 :

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

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

pom.xml:

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

当我做这个请求时,我得到了表示为 UserTest 对象的控制器 JSON。但返回时:

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

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

更新 我找到了解决方案!! 它只需要返回一个对象。不是用户对象或其他东西。 但 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;

【问题讨论】:

  • 需要返回对象。在这种情况下,您无需在配置文件中指定任何内容。

标签: java jquery json spring spring-mvc


【解决方案1】:

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

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

复杂的解决方案是更改使用RequestResponseBodyMethodProcessor 注册的ContentNegotiationStrategy 对象的顺序,该RequestResponseBodyMethodProcessor 处理您的@ResponseBody

【讨论】:

  • 非常感谢您建议调查 ContentNegotiationStrategy!
【解决方案2】:

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

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

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

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

</dependency>

也需要:&lt;mvc:annotation-driven /&gt;

【讨论】:

    【解决方案3】:

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

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

    <mvc:annotation-driven />
    

    改为:

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

    【讨论】:

    • 我快要发疯了。我第一次阅读有关 ContentNegotiation 的内容。我遇到了同样的问题,带有 .html 结尾的遗留应用程序发送了 json。这很疯狂。您为我指明了正确的方向,最终解决了我的问题。每当您在德国时,请 ping 我,您将可以访问无限量的啤酒管道。这个博客也帮助了我,知道了条款后:spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc
    【解决方案4】:

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

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

    我用过Spring 4.1.xJackson 2.4.2

    【讨论】:

      【解决方案5】:

      确保在您的注释中使用produce = "application/json"。

      【讨论】:

      • 正如我在对 Pracede 答案的评论中解释的那样,这些 @RequestMapping 属性值仅限制处理程序方法映射到的内容。通过不指定该值,您已经覆盖了它,因此在这种情况下没有明确的必要。
      猜你喜欢
      • 1970-01-01
      • 2019-04-30
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2018-07-22
      • 2014-11-18
      • 2019-05-05
      • 1970-01-01
      相关资源
      最近更新 更多