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: "Ресурс, идентифицированный этим запросом, способен генерировать ответы только с характеристиками, которые не являются приемлемыми в соответствии с запросом" принять "заголовки ()".
Я также попробовал альтернативный механизм доступа к этому с помощью Javascript
AJAX
чтобы убедиться, что мой заголовок запроса имеет 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
}
У меня была та же проблема, и комментарий, добавленный Бижу Кунджумменом к этому ответу, отлично сработал для меня
То есть есть публичные геттеры в моем классе 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.
Спасибо, что поделились своим опытом. Я столкнулся с той же проблемой, и она работает для меня, используя конфигурацию, как показано ниже:
- Spring MVC Версия: 3.2.5.RELEASE
- Apache-6.0.24-кот
- JDK1.6
- ДЖЕКСОН-ядро-ASL-1.9.10.jar
- ДЖЕКСОН-картограф-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>