将我的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无法接受。
我设法创建了一个带有我无法访问的URL的简化控制器:
@RequestMapping(value = "/resources/foo.js", produces = "text/javascript")
@ResponseBody
public String foo() throws Exception {
return "";
}
由于我正在使用*/*
标头中有Accept
的普通浏览器,我不明白为什么我应该获得HTTP 406.这更让人感到奇怪的是这个代码正在使用Spring 3.1.2,但不适用于Spring 3.2。那是为什么?
答案 0 :(得分:10)
与Spring does content-negotiations in 3.2的方式有关的几处变化。其中一个变化是现在可以根据URL中的文件后缀完成内容协商。默认情况下启用此功能。在3.2之前的Spring版本中,HTTP accept-header用于内容协商。当浏览器访问您的URL时,内容协商很少成为问题,因为浏览器始终发送Accept:(...)*/*
。
Spring有一个后缀=>的地图媒体类型。对于“.js”,默认媒体类型是“application / x-javascript”。当Spring尝试查找请求到/resources/foo.js的处理程序映射时,它将与您的foo()
- 方法不匹配,因为它会生成错误的媒体类型。
我不确定Spring团队是否考虑过这个案例。它至少有点奇怪,它允许您创建一个无法访问的@RequestMapping
(因为.js-media类型与produce字段中设置的不兼容)。
有几种方法可以解决此问题。一种是将produce-parameter更改为“application / x-javascript”。另一种方法是将“.js”的媒体类型更改为“text / javascript”(see the docs of how to do that)。第三种可能性是基于后缀关闭内容协商(同样,see the docs of how to do it)。
答案 1 :(得分: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。
答案 2 :(得分:0)
您需要在配置中添加适当的MessageConverter
,以及杰克逊可能已经拥有的{。}}。
e.g。在您的WebMvcConfigurerAdapter
的子类中:
@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
converters.add(new StringHttpMessageConverter());
}
当您仍然打开favorPathExtension
选项时,您也不需要produces
参数,您的控制器将返回application/javascript
。
当我遇到同样的问题时,Aleksanders的回答实际上并没有帮助我摆脱406。
答案 3 :(得分: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);
}
}