HTTP-статус 406. Spring MVC 4.0, jQuery, JSON
Я хочу отправить JSON с моего контроллера. У меня есть следующая конфигурация.
spring-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<context:component-scan base-package="com.castle.controllers"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
.js:
function testAjax() {
var data = {userName: "MyUsername", password:"Password"};
$.ajax({
url: 'ajax/test.htm',
dataType : 'json',
type : 'POST',
contentType: "application/json",
data: JSON.stringify(data),
success: function(response){
alert('Load was performed.');
}
});
}
UserTest.java:
public class UserTest {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
TestAjaxController.java:
@Controller
@RequestMapping("/ajax")
public class TestAjaxController {
@RequestMapping(method = RequestMethod.POST, value = "/test.htm")
public @ResponseBody
UserTest testAjaxRequest(@RequestBody UserTest user) {
return user;
}
}
pom.xml:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
Когда я делаю этот запрос, я получаю в моем контроллере JSON, представленный как объект UserTest. Но по возвращении:
HTTP-статус 406. - Ресурс, идентифицированный этим запросом, способен генерировать ответы только с характеристиками, не приемлемыми в соответствии с заголовками запроса "принять".
Что я делаю не так? Я знаю, есть много вопросов о таких случаях, но я не могу это исправить в течение 2 дней...
ОБНОВЛЕНИЕ Я нашел решение!! Нужно только вернуть объект. Не объект пользователя или что-то. Но return Object;
public @ResponseBody Object testAjaxRequest(@RequestBody UserTest user) {
List<UserTest> list = new ArrayList<>();
list.add(user);
list.add(user);
list.add(user);
return list;
5 ответов
Основная проблема здесь заключается в том, что путь "/test.htm"
собирается использовать согласование содержимого, прежде чем проверять значение Accept
заголовок. С расширением вроде *.htm
Весной воспользуюсь org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy
и решить, что приемлемый тип носителя для возврата text/html
что не соответствует чему MappingJacksonHttpMessageConverter
производит, т.е. application/json
и, следовательно, 406 возвращается.
Простое решение состоит в том, чтобы изменить путь на что-то вроде /test
, в котором согласование содержимого на основе пути не разрешит любой тип содержимого для ответа. Вместо этого другой ContentNegotiationStrategy
на основе заголовков будет разрешать значение Accept
заголовок.
Сложное решение состоит в том, чтобы изменить порядок ContentNegotiationStrategy
объекты, зарегистрированные в RequestResponseBodyMethodProcessor
который обрабатывает ваш @ResponseBody
,
У меня была та же проблема, в конце концов, это была версия org.codehaus.jackson 1.9.x, когда я переключился с 1.9.x Джексона на 2.x (fastxml) в моем pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.2.3</version>
</dependency>
Также необходимо: <mvc:annotation-driven />
Я столкнулся с этой проблемой при обновлении Spring в устаревшем проекте. .html
Суффикс конечных точек AJAX (которые пытались вернуть JSON) действительно был принудительно создан, чтобы попытаться создать HTML из-за суффикса, и поскольку обработчики возвращали объект, запрос завершился ошибкой 406, поскольку Spring не смог выяснить Как сделать HTML из простого объекта Java.
Вместо того, чтобы изменять суффиксы конечной точки или выполнять полную настройку ContentNegotiationStrategy
внесения этого изменения было достаточно:
<mvc:annotation-driven />
изменился на:
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
</bean>
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
Добавление этих строк в контекстную конфигурацию решило ту же проблему для меня:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
я использовал Spring 4.1.x
а также Jackson 2.4.2
Убедитесь в том, что в ваших аннотациях используется yield = "application/json".