43

在尝试使用 获取我的响应时JSONSpring 3.x我得到406 error“此请求标识的资源只能生成具有根据request“接受”标头 () 不可接受的特征的响应。

这是我的环境

* Spring 3.2.0.RELEASE
* included jackson-mapper-asl-1.7.9.jar, jackson-core-asl-1.7.9.jar
* Tomcat 6.x
* mvc:annotation-driven in Spring configuration XML file

我的控制器:

@RequestMapping("/contest")
public class ContestController {

    @RequestMapping(value="{name}", headers="Accept=*/*", method = RequestMethod.GET)
    public @ResponseBody Contest getContestInJSON(@PathVariable String name) {
        Contest contest = new Contest();
        contest.setName(name);
        contest.setStaffName(new String("contestitem1"));

        return contest;
    }

}

我的 Spring 配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<context:component-scan base-package="com.contestframework.controllers" />

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">

<property name="mediaTypes">
    <map>
      <entry key="atom" value="application/atom+xml"/>
      <entry key="html" value="text/html"/>
      <entry key="json" value="application/json"/>
    </map>
 </property>

 <property name="viewResolvers">
 <list>
  <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
 </list>
 </property>

 <property name="defaultViews">
  <list>
   <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
  </list>
 </property>

 </bean>

<mvc:annotation-driven />

</beans>

在此之后,我只需使用以下方式访问控制器:

http://domain/SpringWebProject/json/contest/abcd

我得到的响应是状态 406:“此请求标识的资源只能生成具有根据请求“接受”标头()不可接受的特征的响应。”

我还尝试了另一种机制,通过访问它Javascript AJAX来确保我的请求标头具有application/JSON,但这导致了相同的状态 406 结果

$.getJSON('contest/abcd', function(data) {
console.log(data) }

这是我从浏览器捕获的请求标头:

Request URL:http://localhost:8080/SpringWebProject/json/contest/abcd
Request Method:GET
Status Code:406 Not Acceptable

Accept:application/json, text/javascript, */*; q=0.01
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=59689C95B0B9C21494EB0AB9D9F7BCCD
Host:localhost:8080
Referer:http://localhost:8080/SpringWebProject/json/welcome
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4
X-Requested-With:XMLHttpRequest
Response Headersview source
Content-Length:1070
Content-Type:text/html;charset=utf-8
Date:Fri, 12 Oct 2012 18:23:40 GMT
Server:Apache-Coyote/1.1

感谢这方面的任何帮助。

4

14 回答 14

49

我也遇到了同样的问题。看来这是最新的 3.2.0.RELEASE 的问题,因为我之前有 3.1.2.RELEASE 并且一切正常。更改为 3.2.0.RELEASE 后,它会中断。已经用 3.1.3.RELEASE 测试过,效果很好。所以现在我建议回滚到 3.1.3.RELEASE

编辑:感谢本网站上链接到以下位置的另一篇文章:http: //static.springsource.org/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-配置内容协商

我现在通过根据请求路径的扩展禁用获取媒体类型来使其工作。这可以通过以下方式完成:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <!-- Turn off working out content type based on URL file extension, should fall back to looking at the Accept headers -->
    <property name="favorPathExtension" value="false" />
</bean>

并为所有 xsd 模式位置指定版本 3.2。

这是使用以下杰克逊罐子:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.1.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.1.2</version>
</dependency>
于 2012-12-18T18:35:17.797 回答
20

您的配置没有任何问题,但让我建议一些小的更改:

a)您的命名空间出现错误 - 它们指的是 3.0 模式,只需将它们更改为 3.1 或不明确引用版本,例如这种方式。

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans.xsd

或者

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

b)您不需要 ContentNegotiatingViewResolver,您可以从配置中删除除component-scanand之外的所有内容<mvc:annotation-driven/>

c) 请求不会直接从浏览器工作,因为它明确需要“application/json”的 Accept 标头 -$.getJson尽管它发送了正确的标头,但调用应该可以工作

d)headers=Acc..从@RequestMapping 中删除,并且还产生,两者都是过滤条件以匹配正确的映射方法调用。

有了这些,就没有理由不提供 json 了,你能试试这些看看效果如何。

于 2012-10-13T12:37:16.597 回答
11

我遇到了同样的问题,我通过添加以下依赖项解决了它

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>${jackson.version}</version>
</dependency>

以前我正在使用以下依赖项

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

简而言之,我已将 com.fasterxml.jackson.core 替换为org.codehaus.jackson

于 2013-12-22T06:46:02.163 回答
8

我在 Spring MVC 4 中遇到了这个问题。添加 jackson-annotations、jackson-core 和 jackson-databind 并没有解决问题。试试这个库:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.9.13</version>
</dependency>
于 2014-08-29T20:10:19.780 回答
7

我认为您需要在您的@RequestMapping 中添加一个produces="application/json" (有一段时间没有看过spring mvc,所以我不是100% 肯定的)...

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html

16.3.2.6 可生产的媒体类型

您可以通过指定可生产媒体类型的列表来缩小主要映射范围。仅当 Accept 请求标头与这些值之一匹配时,才会匹配该请求。此外,使用产生条件可确保用于生成响应的实际内容类型尊重产生条件中指定的媒体类型。例如:

@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {    
    // implementation omitted
}
于 2012-10-12T18:50:20.513 回答
7

我有同样的问题,Biju Kunjummen 在这个答案中添加的评论对我来说非常有用

https://stackoverflow.com/a/12873170/20654

那就是在我的 Java 类中有公共吸气剂

于 2013-08-14T09:50:44.960 回答
6

我有一个类似的问题,当我添加jackson-databind库时它得到了解决。

这些是我的依赖项:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.12</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.3</version>
</dependency>
于 2014-12-12T16:19:21.343 回答
4

感谢您分享您的经验。我遇到了同样的问题,它适用于我使用如下所示的配置:

  1. Spring MVC 版本:3.2.5.RELEASE
  2. Apache-tomcat-6.0.24
  3. JDK1.6
  4. 杰克逊核心asl-1.9.10.jar
  5. jackson-mapper-asl-1.9.10.jar

Spring MVC 配置文件:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- Turn off working out content type based on URL file extension, should fall back to looking at the Accept headers -->
    <property name="favorPathExtension" value="false" />
</bean>

模型类:Country.java

 private Integer countryId;
 private String name;
 //public setters and getters

控制器方法:

@RequestMapping(value = "/get_country_json",method = RequestMethod.GET)
@ResponseBody
public Country getCountry()

部署描述符(web.xml)

 <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>       
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

请求调用控制器方法的 URL:/SpringCURDApp/get_country_json.htm

我希望这可以帮助某人。

于 2014-04-23T09:13:30.833 回答
4

不要犯我犯过的同样的错误,整天玩 Spring 配置,实际上你在 Web 服务中返回的对象没有正确地编组为 XML。似乎 Spring 捕获了一个 JAXB 编组错误并且没有报告它。使用此沙盒代码验证 JAXB 封送处理:

MyClass myclass = new MyClass();
//populate myclass here

JAXBContext context = JAXBContext.newInstance(MyClass.class);

Marshaller m = context.createMarshaller();
StringWriter w = new StringWriter();

m.marshal(myclass, w);
System.out.println(w);

这产生并显示了一个异常。修复了这个原因,我的 Web 服务在 XML 和 JSON 中都可用。

于 2014-09-05T17:59:04.257 回答
3

不久:

对于 Spring MVC 4.1.6 来说已经足够了:

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

jackson-databind依赖于核心注释工件。


详细说明:

什么是HTTP 406错误?

406 Not Acceptable 请求的资源只能生成根据请求中发送的 Accept header 不可接受的内容。

这意味着服务器无法生成Accept Header中规定的MEDIA TYPE的内容。

但是服务器如何知道它可以生成哪些MEDIA TYPE而哪些不能呢?

Spring Web 有HttpMessageConverter的概念。其中一些转换器已经在 Spring 中注册,并且AbstractMessageConverterMethodArgumentResolver将它们保存在属性messageConverters中。

在请求处理期间AbstractMessageConverterMethodProcessor分析 spring 可以转换的内容并将所有支持的MEDIA TYPES保存在producibleMediaTypes变量中。如果请求的媒体类型不可生产,则显示错误 406 == 我无法生成请求的媒体类型。对不起。

长话短说 - 注册所需的转换器。在您的情况下,它是生成application/json的杰克逊库

于 2015-06-10T21:36:43.257 回答
0

请参阅http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config-content-negotiation 如您所见

“对于请求 URI、MVC Java 配置和 MVC 命名空间中的文件扩展名,如果存在相应的依赖项(例如 Jackson、JAXB2 或 Rome),则会自动注册 .json、.xml、.rss 和 .atom 等扩展名类路径。”

您应该在 URI 的末尾添加“.json”(例如http://domain/SpringWebProject/json/contest/abcd.json)它适用于我。

于 2015-06-07T07:23:47.887 回答
0

我有类似的问题,但很奇怪。我将解释我是如何解决的。

在我的 web.xml 中,我的调度程序 servlet 被映射到 *.htm

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

无论我做什么,它总是抛出 -

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

最后我把它改成了

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

它奏效了。我的想法是当你指定

<mvc:annotation-driven/> 

扩展优先于接受标头,而 .htm 正在制造问题。显然我不能使用 xml 或 json,因为 servlet 本身没有被映射。

我还想补充一点,它会产生注释,spring 将尝试映射它将接受传入请求的标头。我正在为 json 和 xml 制作通用的请求处理程序方法。由于我使用的是 Java 8 并且 Jaxb 是 Java 内置的,因为 Java 7 不需要 JAXB 依赖项。对于 json 我只需要添加 -

<dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.8.5"/>

我正在使用常春藤进行依赖管理。

于 2017-01-14T15:55:46.897 回答
0

也许你应该更新你的杰克逊图书馆。我使用 Spring v4.3.8,我使用它如下:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.8.7</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.8.7</version>
</dependency>
于 2017-06-05T08:46:50.833 回答
-1

如果您使用的是 Spring 4,那么您必须只更新您的库:

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

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.0</version>
    </dependency>
于 2015-05-30T06:06:51.617 回答