Spring JSON-запрос на получение 406 (не приемлемо)
Это мой JavaScript:
function getWeather() {
$.getJSON('getTemperature/' + $('.data option:selected').val(), null, function(data) {
alert('Success');
});
}
это мой контроллер:
@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
@ResponseBody
public Weather getTemparature(@PathVariable("id") Integer id){
Weather weather = weatherService.getCurrentWeather(id);
return weather;
}
весна-servlet.xml
<context:annotation-config />
<tx:annotation-driven />
Получение этой ошибки:
GET http://localhost:8080/web/getTemperature/2 406 (Not Acceptable)
Заголовки:
Заголовки ответа
Server Apache-Coyote/1.1
Content-Type text/html;charset=utf-8
Content-Length 1070
Date Sun, 18 Sep 2011 17:00:35 GMT
Заголовки запроса
Host localhost:8080
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept application/json, text/javascript, */*; q=0.01
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection keep-alive
X-Requested-With XMLHttpRequest
Referer http://localhost:8080/web/weather
Cookie JSESSIONID=7D27FAC18050ED84B58DAFB0A51CB7E4
Интересная заметка:
Я получаю ошибку 406, но запрос гибернации пока что работает. Вот что говорит журнал tomcat каждый раз, когда я меняю выбор в dropbox:
select weather0_.ID as ID0_0_, weather0_.CITY_ID as CITY2_0_0_, weather0_.DATE as DATE0_0_, weather0_.TEMP as TEMP0_0_ from WEATHER weather0_ where weather0_.ID=?
В чем может быть проблема? Ранее в SO было два похожих вопроса, я попробовал все принятые намеки, но они не сработали, я думаю...
Какие-либо предложения? Не стесняйтесь задавать вопросы...
26 ответов
406 Недопустимо
Ресурс, идентифицированный запросом, способен генерировать только объекты ответа, которые имеют характеристики контента, неприемлемые в соответствии с заголовками принятия, отправленными в запросе.
Итак, ваш заголовок подтверждения запроса - application/json, и ваш контроллер не может его вернуть. Это происходит, когда не удается найти правильный HTTPMessageConverter, удовлетворяющий аннотированному возвращаемому значению @ResponseBody. HTTPMessageConverter автоматически регистрируются при использовании <mvc:annotation-driven>
, учитывая определенные сторонние библиотеки в classpath.
Либо у вас нет правильной библиотеки Джексона в вашем пути к классам, либо вы не использовали <mvc:annotation-driven>
директивы.
Я успешно воспроизвел ваш сценарий, и он работал нормально, используя эти две библиотеки, и нет headers="Accept=*/*"
директивы.
- ДЖЕКСОН-ядро-ASL-1.7.4.jar
- ДЖЕКСОН-картограф-ASL-1.7.4.jar
У меня была та же проблема, с последней весной 4.1.1 и выше, вам нужно добавить следующие файлы jar в pom.xml.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1.1</version>
</dependency>
также убедитесь, что у вас есть следующий jar:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
406 Spring MVC Json, не принимается согласно запросу "принять" заголовки
В другом случае этот статус будет возвращен: если картограф Джексона не может понять, как сериализовать ваш компонент. Например, если у вас есть два метода доступа для одного и того же логического свойства, isFoo()
а также getFoo()
,
Происходит то, что Spring MappingJackson2HttpMessageConverter вызывает StdSerializerProvider Джексона, чтобы посмотреть, сможет ли он преобразовать ваш объект. В нижней части цепочки вызовов StdSerializerProvider._createAndCacheUntypedSerializer
бросает JsonMappingException
с информативным сообщением. Однако это исключение поглощено StdSerializerProvider._createAndCacheUntypedSerializer
, который сообщает Spring, что он не может конвертировать объект. Spring исчерпал конвертеры и сообщает, что Accept
заголовок, который он может использовать, что, конечно, является поддельным, когда вы даете ему */*
,
В этом поведении есть ошибка, но она была закрыта как "не может воспроизвести": вызываемый метод не объявляет, что он может выдавать, поэтому проглатывание исключений, очевидно, является подходящим решением (да, это был сарказм). К сожалению, у Джексона нет никакой регистрации... и в кодовой базе есть много комментариев, желающих это сделать, поэтому я подозреваю, что это не единственная скрытая ошибка.
У меня была та же проблема, мой метод контроллера выполняется, но ответ - Ошибка 406. Я отлаживаю AbstractMessageConverterMethodProcessor#writeWithMessageConverters
и нашел этот метод ContentNegotiationManager#resolveMediaTypes
всегда возвращается text/html
который не поддерживается MappingJacksonHttpMessageConverter
, Проблема в том, что org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy
работает раньше, чем org.springframework.web.accept.HeaderContentNegotiationStrategy
и продление моего запроса /get-clients.html
является причиной моей проблемы с ошибкой 406. Я просто изменил URL-адрес запроса на /get-clients
,
Убедитесь, что отправленный объект (в данном случае Weather) содержит getter/setter
Убедитесь, что следующие 2 jar
присутствуют в пути к классам.
Если какой-либо один или оба отсутствуют, то эта ошибка придет.
jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar
Наконец-то нашел ответ отсюда:
Картирование успокоительных запросов Ajax к весне
Я цитирую:
@ RequestBody / @ ResponseBody аннотации не используют обычные преобразователи представления, они используют свои собственные HttpMessageConverters. Чтобы использовать эти аннотации, вы должны сконфигурировать эти конвертеры в AnnotationMethodHandlerAdapter, как описано в ссылке (вам, вероятно, понадобится MappingJacksonHttpMessageConverter).
Проверьте <mvc:annotation-driven />
в dispatcherservlet.xml, если не добавить его. И добавить
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
эти зависимости в вашем pom.xml
Вероятно, никто не прокручивает эту страницу так далеко, но ни одно из вышеперечисленных решений не исправило это для меня, но сделал все мои методы получения public
сделал.
Я оставил свой видимость получателя в пакете-частном; Джексон решил, что не может их найти, и взорвался. (С помощью @JsonAutoDetect(getterVisibility=NON_PRIVATE)
только частично исправил это.
У меня возникла та же проблема, потому что мне не хватало аннотации @EnableMvc. (Вся моя весенняя конфигурация основана на аннотациях, XML-эквивалент будет mvc: на основе аннотаций)
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>2.6.3</version>
</dependency>
В контроллере не должна быть аннотация тела ответа на тип возвращаемого значения, а не на метод, например так:
@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
public @ResponseBody Weather getTemparature(@PathVariable("id") Integer id){
Weather weather = weatherService.getCurrentWeather(id);
return weather;
}
Я также использовал бы функцию raw jquery.ajax и убедился, что contentType и dataType установлены правильно.
С другой стороны, пружинная обработка json довольно проблематична. Было проще, когда я делал все сам, используя строки и GSON.
Как уже упоминалось@atott.
Если вы добавили последнюю версию Jackson в ваш файл pom.xml и в Spring 4.0 или новее, используйте @ResponseBody
на ваш метод действий и @RequestMapping
настроен с produces="application/json;charset=utf-8"
Тем не менее, у вас все еще есть 406(не приемлемо), я думаю, вам нужно попробовать это в вашей конфигурации контекста MVC DispatcherServlet:
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
</bean>
Так я наконец решил свою проблему.
Проверьте эту тему. spring mvc restcontroller возвращает строку json p/s: вы должны добавить конфигурацию сопоставления jack son в ваш класс WebMvcConfig
@Override protected void configureMessageConverters( List<HttpMessageConverter<?>> converters) { // put the jackson converter to the front of the list so that application/json content-type strings will be treated as JSON converters.add(new MappingJackson2HttpMessageConverter()); // and probably needs a string converter too for text/plain content-type strings to be properly handled converters.add(new StringHttpMessageConverter()); }
Весна 4.3.10: я использовал приведенные ниже настройки для решения проблемы.
Шаг 1: Добавьте следующие зависимости
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
Шаг 2. Добавьте нижеприведенное в свою конфигурацию контекста MVC DispatcherServlet:
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="ignoreAcceptHeader" value="false" />
</bean>
Начиная с весны 3.2, в соответствии с конфигурацией по умолчанию значение favPathExtension установлено в значение true, из-за этого, если в запросе есть какие-либо надлежащие расширения, такие как .htm
весна будет отдавать приоритет расширению. На шаге 2 я добавил bean-компонент contentNegotiationManager, чтобы переопределить это.
Для людей, которые все еще сталкиваются с ошибкой 406 после добавления ':*' к регулярному выражению переменной пути.
Переопределить приведенный ниже метод интерфейса WebMvcConfigurer в любом классе @Configuration.
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(true)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("com", MediaType.APPLICATION_JSON);
}
Я добавил «com» в качестве расширения, поскольку мы использовали идентификаторы электронной почты в качестве переменной пути и ожидали ответа application/json от нашего приложения.
Это помогает мне решить проблему.
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="ignoreAcceptHeader" value="false" />
</bean>
Однако обратите внимание, что это не включает конкретную конфигурацию, которая была у вас в исходном фрагменте для согласования контента. Итак, если вы включите только<mvc:annotation-driven />
и опуститьcontentNegotiationManager
bean-компонента, приложение будет использовать поведение по умолчанию для согласования содержимого. Поведение по умолчанию обычно включает в себя рассмотрениеAccept
заголовок и, если доступно, расширение файла в URL-адресе, чтобы определить тип носителя ответа.
Убедитесь, что у вас есть правильная версия Джексона в вашем classpath
Это обновленный ответ для springVersion=5.0.3.RELEASE.
Эти ответы выше будут работать только в более старой версии SpringVersion <4.1. для последней весны вы должны добавить следующие зависимости в файл Gradle:
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: fasterxmljackson
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: fasterxmljackson
fasterxmljackson=2.9.4
Я надеюсь, что это будет полезно для тех, кто использует последнюю весеннюю версию.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.0</version>
</dependency>
я не использую аутентификацию ssl, и этот jackson-databind содержит jackson-core.jar и jackson-databind.jar, а затем изменяю содержимое RequestMapping следующим образом:
@RequestMapping(value = "/id/{number}", produces = "application/json; charset=UTF-8", method = RequestMethod.GET)
public @ResponseBody Customer findCustomer(@PathVariable int number){
Customer result = customerService.findById(number);
return result;
}
внимание: если ваш продукт не относится к типу "application/json", и я не заметил этого и получил ошибку 406, помогите вам.
Проверьте, как @joyfun сделал для правильной версии Джексона, но также проверьте наши заголовки... Принять / не может быть передан клиентом... используйте firebug или эквивалентный, чтобы проверить, что на самом деле отправляет ваш запрос на получение. Я думаю, что атрибут заголовков аннотации / может / проверяет литералы, хотя я не уверен на 100%.
Кроме очевидных проблем, у меня была еще одна, которую я не мог исправить независимо от включения всех возможных JAR-файлов, зависимостей и аннотаций в сервлете Spring. В конце концов я обнаружил, что у меня неправильное расширение файла, потому что я имею в виду, что у меня два отдельных сервлета работают в одном и том же контейнере, и мне нужно было сопоставить с различными расширениями файлов, где одно было ".do", а другое использовалось для подписок с произвольным именем ". к югу". Все хорошо, но SUB является допустимым расширением файла, обычно используемым для файлов субтитров фильмов, и, таким образом, Tomcat переопределял заголовок и возвращал что-то вроде "text/x-dvd.sub...", так что все было в порядке, но приложение ожидало JSON, но получало субтитры. Таким образом, все, что мне нужно было сделать, это изменить отображение в моем web.xml
файл, который я добавил:
<mime-mapping>
<extension>sub</extension>
<mime-type>application/json</mime-type>
</mime-mapping>
У меня была та же проблема, к сожалению, ни одно из предложенных здесь решений не решило мою проблему, так как моя проблема была в другом классе.
Сначала я проверил, что все зависимости на месте, как предложено @bekur, затем я проверил запрос / ответ, который передается от клиентов к серверу, все заголовки были правильно установлены Jquery. Затем я проверил RequestMappingHandlerAdapter
MessageConverters
и все 7 из них были на месте, я действительно начал ненавидеть весну! Я потом обновился от весны 4.0.6.RELEASE
в 4.2.0.RELEASE
У меня есть другой ответ, а не выше. это было Request processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type
Вот мой метод контроллера
@RequestMapping(value = "/upload", method = RequestMethod.POST,produces = "application/json")
public ResponseEntity<UploadPictureResult> pictureUpload(FirewalledRequest initialRequest) {
DefaultMultipartHttpServletRequest request = (DefaultMultipartHttpServletRequest) initialRequest.getRequest();
try {
Iterator<String> iterator = request.getFileNames();
while (iterator.hasNext()) {
MultipartFile file = request.getFile(iterator.next());
session.save(toImage(file));
}
} catch (Exception e) {
return new ResponseEntity<UploadPictureResult>(new UploadPictureResult(),HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<UploadPictureResult>(new UploadPictureResult(), HttpStatus.OK);
}
public class UploadPictureResult extends WebResponse{
private List<Image> images;
public void setImages(List<Image> images) {
this.images = images;
}
}
public class WebResponse implements Serializable {
protected String message;
public WebResponse() {
}
public WebResponse(String message) {
this.message = message;
}
public void setMessage(String message) {
this.message = message;
}
}
Решением было сделать UploadPictureResult, чтобы не расширять WebResponse
По какой-то причине Spring не смог определить, как конвертировать UploadPictureReslt при расширении WebResponse.
Простой ответ: просто добавьте метод Getter в класс вашего домена/модели.
Но почему это работает??
Под капотом Spring использовал HttpMessageConverters для преобразования вашего входного JSON в объект Java.
Заголовок Accept , который передается в запросе, используется для выбора соответствующего MessageConvertor во время выполнения. Эти преобразователи сообщений используют геттер вашего класса домена/модели для преобразования, поэтому, если нет метода геттера, Marshall и unmarshall Java Objects в JSON и из него не произойдет, даже если вы добавите Jackson в свой путь к классам, потому что даже Jackson lib использует Getter методы сортировки материалов !!.
при весенней загрузке: представьте, что мы хотим вернуть метод веб-сервиса так же, как:
ResponseEntity.status(HttpStatus.CREATED)
.body(myObject);
myObject class **need to** use @Data annotation from lombok pakage
@Data
public class myClass{
...
}
Можете ли вы удалить элемент заголовков в @RequestMapping и попробовать..
подобно
@RequestMapping(value="/getTemperature/{id}", method = RequestMethod.GET)
Я предполагаю, что spring выполняет проверку содержимого, а не точное совпадение для заголовков accept. Но все же стоит попробовать удалить элемент заголовков и проверить.