Spring 3.x JSON状态406“根据请求不接受的特性”accept“headers()”

时间:2012-10-12 18:33:56

标签: spring spring-mvc

尝试使用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>

在此之后,我只需使用以下内容访问Controller:

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

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

我还尝试了使用Javascript AJAX访问此方法的备用机制,以确保我的请求标头有application/JSON,但这会导致相同的状态406结果

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

这是我从浏览器中捕获的REQUEST HEADER:

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

感谢这方面的任何帮助。

14 个答案:

答案 0 :(得分: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-config-content-negotiation

我现在已经通过根据请求路径的扩展禁用媒体类型来实现它。这可以通过以下方式完成:

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

答案 1 :(得分:19)

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

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

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

OR

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

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

c)请求不会直接在浏览器中运行,因为它明确要求&#34; application / json&#34; - $.getJson调用应该可以正常工作,因为它会发送正确的标题

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

有了这些,没有理由为什么json不应该服用,你能不能试试这些,看看它是怎么回事。

答案 2 :(得分: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>

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

答案 3 :(得分:8)

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

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

答案 4 :(得分:7)

我认为你需要添加一个produce =&#34; application / json&#34;到你的@RequestMapping(一段时间没看过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
}

答案 5 :(得分:7)

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

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

我的Java类中有公共getter

答案 6 :(得分: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>

答案 7 :(得分:4)

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

  1. Spring MVC版本:3.2.5.RELEASE
  2. Apache的Tomcat的6.0.24
  3. JDK1.6
  4. 杰克逊核-ASL-1.9.10.jar
  5. 杰克逊映射器-ASL-1.9.10.jar
  6. 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

    我希望这可以帮助别人。

答案 8 :(得分: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两种版本。

答案 9 :(得分:3)

很快:

对于Spring MVC 4.1.6,已经足够了:

public class BaseClass
{
   public T Control<T>(string controlName, string pageName = null) 
                      where T : class
   {
      By sel = GetSelector(controlName, pageName)
      ...
      return control as T;
   }
   private By GetSelector(string controlName, string pageName = null)
   {
      pageName = string.IsNullOrEmpty(pageName) ?
                 pageMapping[Browser.GetPage()] : pageName;
      ...
      return selector;
   }
}
public class ControlClass : BaseClass
{
   public NgElement NgControl(string controlName, string pageName)
   {
      By sel = GetSelector(controlName, pageName);
      ...
      return element;
   }
   public By GetSelector(string controlName, string pageName)
   {
      pageName = string.IsNullOrEmpty(pageName) ? PageName : pageName;
      pageName = string.IsNullOrEmpty(pageName) ?
                            pageMapping[Browser.GetPage()] : pageName;
      ...
      return selector;
   }
   public string PageName
   {
      get
      {
         ...
         return returnPage.Value;
      }
   }
}
public class DerivedClass1 : ControlClass
{
   //SpecFlow GWT's
   GivenAngularClicks(string controlName)
   {
      WaitForAngular();
      NgControl(crontrolName).Click();
   }
}

jackson-databind 依赖 core annotations 工件。

详情:

什么是 HTTP 406 错误?

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

这意味着服务器无法生成接受标头中 MEDIA TYPE 所述的内容。

但服务器如何知道它可以生成哪些 MEDIA TYPE

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

在请求处理AbstractMessageConverterMethodProcessor期间,分析弹簧可以转换的内容并将所有支持的 MEDIA TYPES 保存在 producibleMediaTypes 变量中。 如果请求 MEDIA TYPE 无法生成,则说错误406 ==我无法生成请求的媒体类型。遗憾。

长话短说 - 注册所需的转换器。在你的情况下,它的jackson库产生 application / json

答案 10 :(得分: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命名空间,自动注册扩展名,如.json,.xml,   .rss和.atom如果相应的依赖项如Jackson,   JAXB2或Rome存在于类路径中。“

你应该在URI的末尾添加“.json”(比如http://domain/SpringWebProject/json/contest/abcd.json) 这个对我有用。

答案 11 :(得分:0)

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

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

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

无论我做了什么总是扔 -

  

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

最后我将其改为

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

它有效。我只想指定

<mvc:annotation-driven/> 

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

我还想添加一个产生注释,你将尝试映射它将接受传入请求的标头。我正在为json和xml创建请求处理程序方法泛型。由于我使用Java 8和Jaxb是用Java构建的,因为Java 7不需要JAXB依赖。对于json我只需要添加 -

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

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

答案 12 :(得分:0)

也许你应该更新你的jackson库。我使用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>

答案 13 :(得分:-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>