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);
}
}