Spring-MVC 406不可接受而不是JSON响应

sti*_*vlo 13 java spring json spring-mvc jackson

我正在尝试使用Spring 3.0.6返回JSON响应,但我得到406响应"Not Acceptable",其描述为:"此请求标识的资源只能生成具有不可接受的特征的响应"请求"接受"标题()."

我知道之前已经提出了一个非常类似的问题,但是我无法让它对我的项目起作用,尽管进行了很多测试并且我不明白我做错了什么.

在我的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>
Run Code Online (Sandbox Code Playgroud)

在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>
Run Code Online (Sandbox Code Playgroud)

在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 />
Run Code Online (Sandbox Code Playgroud)

我的控制器是:

@Controller
public class ClassifiedController {

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

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

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Run Code Online (Sandbox Code Playgroud)

如果我使用以下JQuery:

$.ajax({
        url: '/classified/38001',
        type: 'GET',
        dataType: 'json'
});
Run Code Online (Sandbox Code Playgroud)

发送以下标头:

Accept: application/json, text/javascript, */*; q=0.01
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,结果都是406错误.我不知道还应该检查什么才能让它发挥作用.


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

try {
    return _createAndCacheUntypedSerializer(runtimeType, property);
} catch (Exception e) {
    return null;
}
Run Code Online (Sandbox Code Playgroud)

这是不幸的,因为隐藏了问题的根源.使用调试器,我发现该异常包含一个非常描述性的错误消息:

Conflicting getter definitions for property "reminded": 
ClassifiedImpl#isReminded(0 params) vs
ClassifiedImpl#getReminded(0 params)
Run Code Online (Sandbox Code Playgroud)

现在,我看到错误消息是一个愚蠢的错误,很容易修复,但没有它,这不是那么明显.事实上,修复问题,导致工作序列化.

Tho*_*mas 7

在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>
Run Code Online (Sandbox Code Playgroud)


小智 7

我在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) {
Run Code Online (Sandbox Code Playgroud)

观察:

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

因此:

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

固定:

删除".png"URI中的扩展名,或者删除PathVariable并将其放在正文中,或者在pathVariable后面添加一个后缀(未经测试但也应该可以正常工作),重点是避免URI末尾的文件扩展名.

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


Pau*_*ime 6

MappingJacksonJson处理而言,您需要确保Jackson ObjectMapper支持的序列化对象类型.