HttpMediaTypeNotAcceptableException после обновления до Spring 3.2

после обновления моего приложения 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. Почему так?

4 ответов


было несколько изменений, связанных с how Весна делает контент-переговоры в 3.2. Одно из этих изменений заключается в том, что переговоры по контенту теперь могут выполняться на основе суффикса файла в URL. Эта функция включена по умолчанию. В весенних версиях до 3.2 HTTP accept-header использовался для контент-переговоров. Когда браузеры обращались к вашим URL-адресам, согласование контента редко было проблемой, так как браузер всегда отправляет Accept:(...)*/*.

Весна карта суффикс => Тип носителя. Для." js "тип носителя по умолчанию - " application / x-javascript". Когда Spring пытается найти сопоставление обработчика для запроса к / resources / foo.js, это не будет соответствовать вашему foo() - метод, поскольку он создает неправильный тип носителя.

Я не уверен, что весной команда продумала это дело. По крайней мере, немного странно, что он позволяет создавать @RequestMapping к которому нельзя получить доступ (из-за несовместимости между .JS-тип носителя и то, что установлено в произведениях поле.)

Существует несколько способов устранения этой проблемы. Один из них-изменить параметр produces на "application / x-javascript". Другим было бы изменение типа носителя ".js " to "text / javascript" (см. документы о том, как это сделать). Третья возможность - отключить контент-переговоры на основе суффиксов (опять же, см. документы о том, как это сделать).


теперь я получил его работу, отключив получение типа носителя на основе расширения запрошенного пути. Это можно сделать следующим образом:

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

и укажите версию 3.2 для всех расположений схемы xsd.


вам нужно добавить правильное MessageConverter к вашей конфигурации, вместе с одним вы могли бы уже иметь для Джексона.

например, в подклассе WebMvcConfigurerAdapter:

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

когда вы все еще держите favorPathExtension опция включена, вам не потребуется produces параметр также, ваш контроллер будет возвращать application/javascript.

подсказки в ответе Александра на самом деле не помогли мне избавиться от 406, когда у меня была та же проблема.


У меня есть аналогичная проблема, когда вызов rest контроллеру имеет переменную path, которая содержит .au в значении пути. Весна-это чтение .au как расширение файла из-за согласования содержимого spring

остальные получают вызов http://localhost:8080/api/forgot-password/kk@kudeta.com.au из-за .au в переменной пути Spring бросает org.springframework.сеть.HttpMediaTypeNotAcceptableException

мы решили его отключить контент переговоры

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

}