2012-12-15 101 views
9

升級我的Spring MVC應用到Spring 3.2的一些訪問我的網址的時候,我發現了以下異常之後:HttpMediaTypeNotAcceptableException升級到春天3.2

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 -header具有*/*一個正常的瀏覽器,我不明白爲什麼我應該得到一個HTTP 406.更令人感到奇怪的是,這個代碼與Spring 3.1.2一起工作,但不適用於Spring 3.2。這是爲什麼?

回答

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() -method匹配,因爲它會生成錯誤的媒體類型。

我不確定春季隊是否考慮過這種情況。至少有點奇怪,它可以讓你創建一個無法訪問的@RequestMapping(因爲.js-media類型與生產字段中設置的內容不兼容)。

有幾種方法可以解決這個問題。一個是將生產參數更改爲「application/x-javascript」。另一種方法是將「.js」的媒體類型更改爲「text/javascript」(see the docs of how to do that)。第三種可能性是關閉基於後綴的內容協商(再次,see the docs of how to do it)。

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。

+0

如果使用WebMvcConfigurerAdapter嘗試 @覆蓋 公共無效configureContentNegotiation (ContentNegotiationConfigurer配置器){ \t super.configureContentNegotiation(configurer); \t configurer.favorPathExtension(false); } –

0

您需要爲您的配置添加一個合適的MessageConverter,以及您可能已經擁有的用於Jackson的配置。

例如在你的WebMvcConfigurerAdapter子類:

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

當你仍然保持favorPathExtension選項打開,你將不需要0​​參數以及,控制器將返回application/javascript

Aleksanders答案中的提示實際上並沒有幫助我擺脫406當我有同樣的問題。

0

我有一個類似的問題,其餘調用控制器的路徑變量包含路徑值中的.au。 春天正在讀書。Au作爲由於彈簧內容協商

REST GET調用文件擴展的 http://localhost:8080/api/forgot-password/[email protected] 由於.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); 
    } 

} 
相關問題