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

发布于 2024-12-05 18:00:05 字数 3043 浏览 1 评论 0原文

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

我知道 以前曾问过一个非常相似的问题,但我无法让它适用于我的项目,尽管有很多 测试,我不明白我做错了什么。

在我的 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)

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

I'm trying to return a JSON response with Spring 3.0.6, but I get a 406 response "Not Acceptable", with the description:
"The resource identified by this request is only capable of generating responses with characteristics
not acceptable according to the request "accept" headers ()."

I know that a very similar question has been asked before, but I can't make it work for my project, despite many
tests and I don't understand what I'm doing wrong.

In my Maven pom.xml I've the following:

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

In web.xml I reference webmvc-config.xml, and the log confirms that is loaded.

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

In webmvc-config.xml I've the following:

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

My Controller is:

@Controller
public class ClassifiedController {

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

I tried with or without the headers parameter with the same results. If I call the URL
directly with Firefox the Request Headers contain the following (checked with firebug):

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

If I use the following JQuery:

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

The following headers are sent:

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

In both cases the result is a 406 error. I don't know what else should I check to make
it work.


UPDATE: I decided to debug through Spring and I found out that Jackson was called correctly and in org.codehaus.jackson.map.ser.StdSerializerProvider the method _findExplicitUntypedSerializer contains the following code:

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

This is unfortunate because hides the source of the problem. With the debugger I found out that that exception contained a very descriptive error message:

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

Now that I see the error message is a silly mistake and easy to fix, but without that it wasn't that obvious. In fact, fixing the problem, leaded to a working serialization.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

昔日梦未散 2024-12-12 18:00:05

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

Add the following in 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>
伤感在游骋 2024-12-12 18:00:05

我在 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并将其放入正文中,或者在pathVariable后面添加后缀(未测试但应该也可以工作),重点是避免在 URI 末尾使用文件扩展名。

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

I've stumbled upon the same error (406: content not acceptable) with Spring MVC and @RestController annotation.

The Spring handler:

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

Observation:

  • the URI has the form : http://www.host.com/stuff-acknowledgment/{id}
  • BUT $id has a very particular format: xxxcomplicatedhashxxx.png (or whatever extension you can think of).

Therefore:

Spring MVC interpret the extension and want to produce a result of that same mime type (even if I define it as a path variable), here an "image/png" MIME type even if I tell him to produce JSON. So a 406 exception is thrown.

Fix:

Remove the ".png" extension in the URI, or remove the PathVariable and put it in the body, or add a suffix behind the pathVariable (not tested but should work as well), the point is to avoid a file extension at the end of the URI.

P.S.: I know it doesn't answer the specific problem (with the solution in the update) in the question but I found that SO thread when searching for that problem and post my fix here for the record, hoping it can help someone in the future.

自此以后,行同陌路 2024-12-12 18:00:05

In terms of the MappingJacksonJson processing, you'll need to make sure that the Jackson ObjectMapper supports your object type for serialisation.

始终不够爱げ你 2024-12-12 18:00:05

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

I ran into this problem because the objects that I wanted to return as JSON didn't have any getter methods for their properties. Jackson probably needs these. After adding them it worked.

情仇皆在手 2024-12-12 18:00:05

虽然这个线程有点旧...

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

org.codehaus.jacksonjackson-mapper-asl1.9.13

although this thread is a little old...

u need to add the following (maven dependency):

org.codehaus.jacksonjackson-mapper-asl1.9.13

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文