9

将我的 Spring MVC 应用程序升级到 Spring 3.2 后,访问我的一些 URL 时出现以下异常:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:203) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:272) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:212) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:55) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:297) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1091) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1076) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:896) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915) [spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
(...)

此异常会导致 HTTP 406 NOT ACCEPTABLE。

我设法创建了一个带有我无法访问的 URL 的简化控制器:

@RequestMapping(value = "/resources/foo.js", produces = "text/javascript")
@ResponseBody
public String foo() throws Exception {
    return "";
}

由于我使用的是带有 -header 的普通浏览器*/*Accept所以我不明白为什么我应该获得 HTTP 406。更奇怪的是,这段代码适用于 Spring 3.1.2,但不适用于 Spring 3.2. 这是为什么?

4

4 回答 4

10

Spring 在 3.2 中进行内容协商的方式发生了一些变化。其中一项更改是现在可以根据 URL 中的文件后缀来进行内容协商。默认情况下启用此功能。在 Spring 3.2 之前的版本中,HTTP 接受标头用于内容协商。当浏览器访问您的 URL 时,内容协商很少成为问题,因为浏览器总是发送Accept:(...)*/*.

Spring 有一个后缀 => 媒体类型的映射。对于“.js”,默认媒体类型是“application/x-javascript”。当 Spring 尝试查找对 /resources/foo.js 的请求的处理程序映射时,它不会匹配您的foo()-method,因为它会产生错误的媒体类型。

我不确定 Spring 团队是否考虑过这个案例。至少有点奇怪,它允许您创建一个@RequestMapping无法访问的对象(因为 .js-media 类型与在生产字段中设置的内容不兼容)。

有几种方法可以解决此问题。一种是将生产参数更改为“application/x-javascript”。另一个是将“.js”的媒体类型更改为“text/javascript”(请参阅​​如何执行此操作的文档)。第三种可能性是关闭基于后缀的内容协商(同样,请参阅如何做的文档)。

于 2012-12-15T21:17:26.350 回答
2

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

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

于 2013-07-02T08:13:30.210 回答
0

您需要为MessageConverter您的配置添加一个正确的,以及您可能已经为 Jackson 拥有的一个。

例如在您的子类中WebMvcConfigurerAdapter

@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
    converters.add(new StringHttpMessageConverter());
}

当您仍然打开该favorPathExtension选项时,您也不需要produces参数,您的控制器将返回application/javascript.

当我遇到同样的问题时,Aleksanders 回答中的提示实际上并没有帮助我摆脱 406。

于 2014-09-16T14:31:02.210 回答
0

我有一个类似的问题,其中对控制器的休息调用具有路径变量,其中包含路径值中的 .au。由于 Spring Content Negotiation,Spring 正在读取 .au 作为文件扩展名

REST GET 调用是 http://localhost:8080/api/forgot-password/kk@kudeta.com.au 由于路径变量中的 .au Spring 抛出 org.springframework.web.HttpMediaTypeNotAcceptableException

我们通过关闭基于内容的协商解决了这个问题

@Configuration
public class ContentNegotiationConfig extends WebMvcConfigurerAdapter{
    @Override
    public void configureContentNegotiation(final 
     ContentNegotiationConfigurer configurer) {
        // Turn off suffix-based content negotiation
        configurer.favorPathExtension(false);
    }

}
于 2017-09-08T16:56:16.513 回答