Spring 3 + JSON 的问题:HTTP 状态 406?

Posted

技术标签:

【中文标题】Spring 3 + JSON 的问题:HTTP 状态 406?【英文标题】:Problem with Spring 3 + JSON : HTTP status 406? 【发布时间】:2011-06-26 08:38:54 【问题描述】:

我试图在我的 SpringMVC 3.0 项目中通过 Ajax 发送州名称来获取城市列表。 为此,我在 JSP 中使用了以下调用(使用 jQuery):

    <script type="text/javascript">
function getCities() 
    jq(function() 
        jq.post("getCities.html",
                       stateSelect:  jq("#stateSelect").val(),
                        function(data)
                            jq("#cities").replaceWith('<span id="cities">Testing</span>');
                    );
    );

</script>

这是我的控制器代码:

@RequestMapping(value = "/getCities", method = RequestMethod.POST)
    public @ResponseBody List<StateNames> getCities(@RequestParam(value="stateSelect", required=true) String stateName,
                                Model model) 
        // Delegate to service to do the actual adding
        List<StateNames> listStates = myService.listCityNames(stateName);

        // @ResponseBody will automatically convert the returned value into JSON format
        // You must have Jackson in your classpath
        return listStates;
    

但是当我运行它时,我收到 HTTP 406 错误,说明以下内容: 406 不可接受 请求的资源只能生成根据请求中发送的 Accept headers 不可接受的内容。

我在我的 Maven 依赖项中使用了 Jackson,并在我的上下文文件中进行了定义。 我已经广泛搜索,我猜问题是@ResponseBody 没有自动将我的列表转换为适当的 JSON 对象。

我的萤火虫说:

Response Headers  
Server  Apache-Coyote/1.1  
Content-Type    text/html;charset=utf-8  
Content-Length  1070  
Date    Sat, 12 Feb 2011 13:09:44 GMT  

Request Headers  
Host    localhost:8080  
User-Agent  Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13  
Accept  */*  
Accept-Language en-us,en;q=0.5  
Accept-Encoding gzip,deflate  
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7  
Keep-Alive  115  
Connection  keep-alive  
Content-Type    application/x-www-form-urlencoded; charset=UTF-8  
X-Requested-With    XMLHttpRequest  
Referer http://localhost:8080/MyApplication/  
Content-Length  17  
Cookie  JSESSIONID=640868A479C40792F8AB3DE118AF12E0  
Pragma  no-cache  
Cache-Control   no-cache 

请指导我。我究竟做错了什么??救命!!

【问题讨论】:

这在Spring JSON request getting 406 (not Acceptable)中有更全面的介绍 【参考方案1】:

使用 jQuery,您可以将 contentType 设置为所需的类型(此处为 application/json; charset=UTF-8')并在服务器端设置相同的标头。

记住在测试时清除缓存。

【讨论】:

【参考方案2】:

我在使用 Apache HTTPClient 调用一些服务时也遇到了类似的问题。问题是客户端而不是服务器。我使用了 HTTPRequester,其标头接受 application/json,它运行良好。

【讨论】:

应该是评论而不是答案。【参考方案3】:

正如 Peter 在他的评论中所写,问题的原因是 Spring 无法加载 Jackson。默认情况下,它不由依赖项加载。添加依赖后

  <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.2</version>
  </dependency>

在浏览器中输入地址后返回 JSON,没有任何带有 Accept 标头的技巧(正如它应该做的那样)。

在 Tomcat 7.0 上测试。

【讨论】:

【参考方案4】:

问题不在服务器端,而在客户端。

仔细看错误信息:请求的资源(由服务器端生成)只能生成内容(JSON)不可接受(由客户端!)根据请求中发送的 Accept 标头。

检查您的请求标头:

接受 */*

试试这个方法:

function getCities() 
    jq(function() 
        jq.post(
            "getCities.html",                          // URL to post to
             stateSelect: jq("#stateSelect").val() , // Your data
            function(data)                            // Success callback
                jq("#cities").replaceWith('<span id="cities">Testing</span>');
            ,
            "json"                                     // Data type you are expecting from server
        );
    );

这会将您的 Accept 标头更改为以下内容(从 jQuery 1.5 开始):

接受:应用程序/json、文本/javascript、*/*; q=0.01

这将明确地告诉服务器端您期待 JSON。

【讨论】:

看来如果没有加载Jackson库,Spring app不会提供application/json从而触发406。注意原来的/的请求Accept header应该表示“任何东西”。【参考方案5】:

您的响应内容类型不正确,它应该是 application/json。

您需要将 jackson 添加到您的 /lib 目录。

你应该有

<mvc:annotation-driven /> 

在您的 serlvet-name.xml 文件中。

此外,我建议您将您的请求映射为 get 并尝试使用 Google Chrome 浏览它,看看它是否返回正确的结果。它具有非常好的 json 表示。

【讨论】:

这是我缺少的库。记录一下:必要的 Maven 组/工件组合是 org.codehaus.jackson/jackson-mapper-asl,我刚刚找到的最新版本是 1.9.0(虽然网站上说的是 1.9.1)。

以上是关于Spring 3 + JSON 的问题:HTTP 状态 406?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Controller 未将 JSON 数据返回到 Angular http GET 调用

Spring Boot 中的 JSON 解析

使用 REST 模板和 JSON 响应格式在 Spring MVC 上返回 Http Status 500

带有 MVC 的 Spring 3 JSON

Spring 4.1.1 RELEASE 和 @ResponseBody 返回 HTTP 406

SpringMVC之JSON交互