【问题标题】:Spring-MVC 406 Not Acceptable instead of JSON ResponseSpring-MVC 406 不可接受而不是 JSON 响应
【发布时间】:2011-11-20 08:54:08
【问题描述】:

我正在尝试使用 Spring 3.0.6 返回一个 JSON 响应,但我得到一个 406 响应“不可接受”,其描述如下: “此请求标识的资源只能生成具有特征的响应 根据请求“接受”标头()不可接受。”

我知道a very similar question 之前有人问过,但我无法让它适用于我的项目,尽管有很多 测试,我不明白我做错了什么。

在我的 Maven pom.xml 中,我有以下内容:

<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.8.5</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-core-asl</artifactId>
  <version>1.8.5</version>
  <scope>compile</scope>
</dependency>

在 web.xml 中我引用了 webmvc-config.xml,并且日志确认已加载。

<servlet>
    <servlet-name>mainServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

在 webmvc-config.xml 我有以下内容:

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
    </bean> 
    <mvc:annotation-driven />

我的控制器是:

@Controller
public class ClassifiedController {

    @RequestMapping(value = "/classified/{idClassified}", headers = "Accept=*/*",
                    method = RequestMethod.GET)
    @ResponseBody
    public final Classified getClassified(@PathVariable final int idClassified) {
        ...

我尝试使用或不使用 headers 参数,结果相同。如果我调用 URL 直接使用 Firefox 请求标头包含以下内容(使用 firebug 检查):

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

如果我使用以下 JQuery:

$.ajax({
        url: '/classified/38001',
        type: 'GET',
        dataType: 'json'
});

发送以下标头:

Accept: application/json, text/javascript, */*; q=0.01

在这两种情况下,结果都是 406 错误。我不知道我还应该检查什么 它工作。


更新:我决定通过 Spring 进行调试,我发现 Jackson 被正确调用,并且在 org.codehaus.jackson.map.ser.StdSerializerProvider 方法 _findExplicitUntypedSerializer 包含以下代码:

try {
    return _createAndCacheUntypedSerializer(runtimeType, property);
} catch (Exception e) {
    return null;
}

这很不幸,因为隐藏了问题的根源。通过调试器,我发现该异常包含一个非常具有描述性的错误消息:

Conflicting getter definitions for property "reminded": 
ClassifiedImpl#isReminded(0 params) vs
ClassifiedImpl#getReminded(0 params)

现在我看到错误消息是一个愚蠢的错误并且很容易修复,但没有它就不是那么明显了。事实上,解决问题后,序列化就可以工作了。

【问题讨论】:

  • 你检查了输出的编码/我认为它们在 json heder 内容中有一些限制
  • Accept 是否适用于 @RequestMapping 注释? static.springsource.org/spring/docs/current/… - 可能建议“content-type”。
  • 您是否在上下文中创建了另一个 AnnotationHandlerMapping bean?
  • @nidhin,您的意思是在请求标头中吗?我有这个: Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
  • @Paul Grime,我认为两者都可以接受,无论如何我尝试使用 headers = "content-type=*/*" 现在我有一个 404。

标签: java json spring spring-mvc jackson


【解决方案1】:

MappingJacksonJson 处理而言,您需要确保Jackson ObjectMapper 支持your object type 进行序列化。

【讨论】:

  • 谢谢保罗的帮助,你说的很有道理。但是,我尝试将 Serializable 接口添加到我的 Classified 接口:“public interface Classified extends Serializable”,我仍然有 406,在这两种情况下:返回接口或具体实现。
  • 这不是 java.io 序列化。 Jackson Serializer 需要在 Jackson 注册。阅读 ObjectMapper 和 jackson.codehaus.org/1.8.4/javadoc/org/codehaus/jackson/map/… 的文档。
  • 老兄,你是救世主。谢谢。
【解决方案2】:

虽然这个帖子有点老了……

你需要添加以下(maven依赖):

org.codehaus.jacksonjackson-mapper-asl1.9.13

【讨论】:

    【解决方案3】:

    在 DispatcherServlet-servlet.xml 中添加以下内容。

    <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jacksonMessageConverter"/>
            </list>
        </property>
    </bean>
    

    【讨论】:

      【解决方案4】:

      我遇到了这个问题,因为我想以 JSON 形式返回的对象没有任何用于其属性的 getter 方法。杰克逊可能需要这些。添加它们后,它起作用了。

      【讨论】:

        【解决方案5】:

        我在 Spring MVC 和 @RestController 注释中偶然发现了同样的错误(406:内容不可接受)。

        Spring 处理程序:

        @RequestMapping(value = "/stuff-acknowledgment/{id}", produces ="application/json;charset=UTF-8", headers="Accept=*")
        public Message acknowledgeStuff(@PathVariable("id") String id, @ModelAttribute("ack") AckBean acquittement) {
        

        观察:

        • URI 的格式为:http://www.host.com/stuff-acknowledgment/{id}
        • 但是$id 有一个非常特殊的格式:xxxcomplicatedhashxxx.png(或任何你能想到的扩展名)。

        因此:

        Spring MVC 解释扩展并希望生成相同的 MIME 类型的结果(即使我将其定义为路径变量),这里是 "image/png" MIME 类型,即使我告诉他生成 JSON。所以抛出 406 异常。

        修复:

        去掉URI中的".png"扩展名,或者去掉PathVariable放到body里面,或者在pathVariable后面加一个后缀(没测试但是应该也可以),关键是要避免文件扩展名在URI 的结尾。

        PS:我知道它没有回答问题中的具体问题(更新中的解决方案),但我在搜索该问题时发现了 SO 线程,并在此处发布我的修复记录,希望它可以提供帮助未来的某个人。

        【讨论】:

        • 同样的事情,端点在最后有一个电子邮件地址,导致解释 TLD 扩展,如 value=someServer/{folder}/{email} 。我交换了论点,一切正常。我希望我能为这个答案投票更多,谢谢 agin :)
        猜你喜欢
        • 2013-04-26
        • 1970-01-01
        • 1970-01-01
        • 2014-12-24
        • 2013-03-18
        • 2015-05-17
        • 2019-04-30
        • 1970-01-01
        相关资源
        最近更新 更多