升级到Spring 3.2后出现HttpMediaTypeNotAcceptableException

将我的Spring MVC应用程序升级到Spring 3.2后,在访问我的一些URL时遇到以下exception:

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] (...) 

此exception导致HTTP 406无法接受。

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

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

因为我在Accept -header中使用普通的浏览器*/* ,所以我不明白为什么我应该得到一个HTTP 406.这更加奇怪的是这个代码正在使用Spring 3.1.2,但不是Spring 3.2。 这是为什么?

有关Spring如何在3.2中进行内容协商的一些变化。 其中一个变化是现在可以根据URL中的文件后缀完成内容协商。 默认情况下启用此function。 在3.2之前的Spring版本中,HTTP accept-header用于内容协商。 当浏览器访问您的URL时,内容协商很少成为问题,因为浏览器总是发送Accept:(...)*/*

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

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

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

我现在通过根据请求路径的扩展禁用媒体类型来实现它。 这可以通过以下方式完成:

       

并为所有xsd架构位置指定版本3.2。

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

例如,在WebMvcConfigurerAdapter的子类中:

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

当你仍然保持favorPathExtension选项打开时,你也不需要favorPathExtension参数,你的控制器将返回application/javascript

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

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

REST GET调用是 http:// localhost:8080/api/forgot-password/kk@kudeta.com.au,因为路径变量中的.au正在抛出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); } }