Spring 3.x JSON статус 406 "характеристики не приемлемы по запросу" принять "заголовки ()"

При попытке получить мой ответ в JSON с помощью Spring 3.xЯ получаю 406 error "Ресурс, указанный в этом запросе, способен генерировать ответы только с характеристиками, не приемлемыми в соответствии с request "принять" заголовки ()."

Вот мое окружение

* Spring 3.2.0.RELEASE
* included jackson-mapper-asl-1.7.9.jar, jackson-core-asl-1.7.9.jar
* Tomcat 6.x
* mvc:annotation-driven in Spring configuration XML file

Мой контроллер:

@RequestMapping("/contest")
public class ContestController {

    @RequestMapping(value="{name}", headers="Accept=*/*", method = RequestMethod.GET)
    public @ResponseBody Contest getContestInJSON(@PathVariable String name) {
        Contest contest = new Contest();
        contest.setName(name);
        contest.setStaffName(new String("contestitem1"));

        return contest;
    }

}

Конфигурационный файл My Spring

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<context:component-scan base-package="com.contestframework.controllers" />

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">

<property name="mediaTypes">
    <map>
      <entry key="atom" value="application/atom+xml"/>
      <entry key="html" value="text/html"/>
      <entry key="json" value="application/json"/>
    </map>
 </property>

 <property name="viewResolvers">
 <list>
  <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
 </list>
 </property>

 <property name="defaultViews">
  <list>
   <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
  </list>
 </property>

 </bean>

<mvc:annotation-driven />

</beans>

После этого я просто получить доступ к контроллеру, используя ниже:

http://domain/SpringWebProject/json/contest/abcd

и ответ, который я получаю, - это статус 406: "Ресурс, идентифицированный этим запросом, способен генерировать ответы только с характеристиками, которые не являются приемлемыми в соответствии с запросом" принять "заголовки ()".

Я также попробовал альтернативный механизм доступа к этому с помощью JavascriptAJAX чтобы убедиться, что мой заголовок запроса имеет application/JSON но это привело к тому же результату статуса 406

$.getJSON('contest/abcd', function(data) {
console.log(data) }

Вот мой ЗАГОЛОВОК ЗАПРОСА, захваченный из браузера:

Request URL:http://localhost:8080/SpringWebProject/json/contest/abcd
Request Method:GET
Status Code:406 Not Acceptable

Accept:application/json, text/javascript, */*; q=0.01
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=59689C95B0B9C21494EB0AB9D9F7BCCD
Host:localhost:8080
Referer:http://localhost:8080/SpringWebProject/json/welcome
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4
X-Requested-With:XMLHttpRequest
Response Headersview source
Content-Length:1070
Content-Type:text/html;charset=utf-8
Date:Fri, 12 Oct 2012 18:23:40 GMT
Server:Apache-Coyote/1.1

Ценю любую помощь в этом отношении.

14 ответов

Решение

В вашей конфигурации нет ничего плохого, позвольте мне предложить несколько небольших изменений:

а) Ваши пространства имен кажутся неправильными - они ссылаются на схемы 3.0, просто измените их на 3.1 или не обращайтесь к версии явно, например, так.

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans.xsd

ИЛИ ЖЕ

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

б) вам не требуется ContentNegotiatingViewResolver, вы можете удалить все, кроме component-scan а также <mvc:annotation-driven/> из вашей конфигурации

c) Запрос не будет работать напрямую из браузера, так как для него явно требуется заголовок Accept "application/json" - $.getJson вызов должен работать, хотя он отправляет правильные заголовки

г) удалить headers=Acc.. из @RequestMapping, а также производит, оба являются критериями фильтрации, чтобы соответствовать правильному сопоставленному вызову метода.

С этим, нет никакой причины, почему JSON не должен быть обслужен, пожалуйста, попробуйте с этим и посмотрите, как это происходит.

Я также только что испытал эту же проблему. Казалось бы, это проблема с последней версией 3.2.0.RELEASE, как у меня ранее было 3.1.2.RELEASE, и все это работало. После изменения на 3.2.0. ВЫПУСКАЕТСЯ сломается. Протестировал с 3.1.3.RELEASE, и это прекрасно работает. Так что на данный момент я бы предложил откат к 3.1.3.

РЕДАКТИРОВАТЬ: Спасибо еще один пост на этом сайте, который связан со следующим местоположением: http://static.springsource.org/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html

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

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

И это использует следующие банки Джексона:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.1.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.1.2</version>
</dependency>

У меня была такая же проблема, и я решил ее, добавив следующую зависимость

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>${jackson.version}</version>
</dependency>

Ранее я делаю это со следующей зависимостью

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

Короче говоря, я должен заменить com.fasterxml.jackson.core на org.codehaus.jackson

У меня была эта проблема в Spring MVC 4. Добавление аннотаций jackson, core-jackson и jackson-databind не решило проблему. Попробуйте это libs:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.9.13</version>
</dependency>

Я думаю, что вам нужно добавить в ваш @RequestMapping файлродукт = "application / json" (я давно не смотрел на Spring mvc, поэтому я не на 100% уверен)...

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html

16.3.2.6. Типы производимых носителей

Вы можете сузить первичное сопоставление, указав список производимых типов носителей. Запрос будет сопоставлен только в том случае, если заголовок запроса Accept соответствует одному из этих значений. Кроме того, использование условия приводит к тому, что фактический тип содержимого, используемый для генерации ответа, учитывает типы мультимедиа, указанные в условии создания. Например:

@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {    
    // implementation omitted
}

У меня была та же проблема, и комментарий, добавленный Бижу Кунджумменом к этому ответу, отлично сработал для меня

/questions/4544206/spring-3x-json-status-406-harakteristiki-ne-priemlemyi-po-zaprosu-prinyat-zagolovki/4544222#4544222

То есть есть публичные геттеры в моем классе Java

У меня была похожая проблема, она была решена, когда я добавил jackson-databind библиотека.

Это мои зависимости:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.12</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.3</version>
</dependency>

Не делайте ту же ошибку, что и я, проведите весь день, играя с конфигурацией Spring, когда на самом деле ваш объект, возвращаемый в веб-сервисе, неправильно маршалирует в XML. Кажется, что Spring обнаруживает ошибку маршалинга JAXB и не сообщает об этом. Используйте этот код песочницы для проверки маршалинга JAXB:

MyClass myclass = new MyClass();
//populate myclass here

JAXBContext context = JAXBContext.newInstance(MyClass.class);

Marshaller m = context.createMarshaller();
StringWriter w = new StringWriter();

m.marshal(myclass, w);
System.out.println(w);

Это произвело и показало исключение. Устранена причина, и мой веб-сервис доступен как в формате XML, так и в формате JSON.

Спасибо, что поделились своим опытом. Я столкнулся с той же проблемой, и она работает для меня, используя конфигурацию, как показано ниже:

  1. Spring MVC Версия: 3.2.5.RELEASE
  2. Apache-6.0.24-кот
  3. JDK1.6
  4. ДЖЕКСОН-ядро-ASL-1.9.10.jar
  5. ДЖЕКСОН-картограф-ASL-1.9.10.jar

Файл конфигурации Spring MVC:

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

Модельный класс: Country.java

 private Integer countryId;
 private String name;
 //public setters and getters

Метод контроллера:

@RequestMapping(value = "/get_country_json",method = RequestMethod.GET)
@ResponseBody
public Country getCountry()

Дескриптор развертывания (web.xml)

 <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>       
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

URL, запрошенный для вызова метода контроллера: /SpringCURDApp/get_country_json.htm

Я надеюсь, что это может кому-то помочь.

Коротко:

Для Spring MVC 4.1.6 достаточно:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.5.0</version>
</dependency>

jackson-databind зависит от ядра и артефактов аннотаций.


Подробно:

Что такое ошибка HTTP 406?

406 Неприемлемо Запрашиваемый ресурс способен генерировать контент, неприемлемый только в соответствии с заголовками Accept, отправленными в запросе.

Это означает, что Сервер не может генерировать контент, тип которого указан в заголовке " Принять".

Но как сервер узнает, какой тип медиа он может генерировать, а какой нет?

Spring Web имеет концепцию HttpMessageConverter. Некоторые из этих преобразователей уже зарегистрированы в Spring, и AbstractMessageConverterMethodArgumentResolver хранит их в свойстве messageConverters.

Во время обработки запроса AbstractMessageConverterMethodProcessor анализирует, в какую пружину можно преобразовать, и сохраняет все поддерживаемые ТИПЫ МЕДИА в переменной producibleMediaTypes. Если запрошенный MEDIA TYPE не может быть воспроизведен, появляется ошибка 406 == Я не могу сгенерировать запрошенный тип носителя. Сожалею.

Короче говоря - зарегистрируйте необходимые конвертеры. В вашем случае это библиотека Джексона, которая производит application/json

Пожалуйста, смотрите http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html Как вы можете видеть

"Для расширений файлов в URI запроса, конфигурации MVC Java и пространстве имен MVC автоматически регистрируйте расширения, такие как.json, .xml, .rss и.atom, если соответствующие зависимости, такие как Jackson, JAXB2 или Rome, присутствуют на путь к классу."

Вы должны добавить ".json" в конце URI (например, http://domain/SpringWebProject/json/contest/abcd.json). Это работает для меня.

Может быть, вы должны обновить свою библиотеку Джексона. Я использую Spring v4.3.8, и я использую его следующим образом:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.8.7</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.8.7</version>
</dependency>

У меня была похожая проблема, но это было странно. Я объясню, как я решил это.

В моем web.xml мой сервлет диспетчера был сопоставлен с *.htm

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

и что бы я ни делал, его всегда бросали -

Ресурс, идентифицированный этим запросом, способен генерировать ответы только с характеристиками, не приемлемыми согласно заголовку "принять" запроса.

Наконец я изменил его на

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

и это сработало. Что я думаю, когда вы просто указываете

<mvc:annotation-driven/> 

расширение имеет приоритет над заголовком accept, и.htm создавал проблемы. И, очевидно, я не мог использовать xml или json, поскольку сам сервлет не отображался.

Я также хотел бы добавить, что выдает аннотацию, которую вы, весной, попытаетесь отобразить, примет заголовок входящего запроса. Я делал общий метод обработчика запросов для json и xml. Так как я использую Java 8, а Jaxb встроен в Java, так как Java 7 не нуждается в зависимости JAXB. Для JSON мне нужно было только добавить -

<dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.8.5"/>

Я использую плющ для управления зависимостями.

Если вы используете Spring 4, то вам нужно только обновить ваши библиотеки:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.3.0</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.0</version>
    </dependency>
Другие вопросы по тегам