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

Другие вопросы по тегам