Spring JSON-запрос на получение 406 (не приемлемо)

77

это мой 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;
}

spring -servlet.xml

<context:annotation-config />
<tx:annotation-driven />

Получение этой ошибки:

GET http://localhost:8080/web/getTemperature/2 406 (Not Acceptable)

Headers:

Заголовки ответов

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 были два похожих вопроса, я пробовал все принятые там намеки, но они не работали, я думаю...

Любые предложения? Не стесняйтесь задавать вопросы...

Теги:
spring

22 ответа

107
Лучший ответ

406 Не приемлемо

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

Итак, ваш заголовок запроса принимает заголовок application/json, и ваш контроллер не может его вернуть. Это происходит, когда правильный HTTPMessageConverter не может быть найден, чтобы удовлетворить аннотированное возвращаемое значение @ResponseBody. HTTPMessageConverter автоматически регистрируется, когда вы используете <mvc:annotation-driven>, учитывая определенные 3-сторонние библиотеки сторон в пути к классам.

Либо у вас нет правильной библиотеки Джексона в вашем пути к классам, либо вы не использовали <mvc:annotation-driven>.

Я успешно реплицировал ваш сценарий и отлично работал с этими двумя библиотеками и директивой headers="Accept=*/*".

  • ДЖЕКСОНА-ядро-ASL-1.7.4.jar
  • ДЖЕКСОНА-картографа-ASL-1.7.4.jar
  • 0
    Нет, это не было проблемой, проверьте мой ответ.
  • 0
    Если настройка HttpMessageConverters вручную решит вашу проблему, то использование mvc: annotation-driven сделает то же самое, что и автоматическая настройка конвертеров и HandlerAdapters (HA). Обратите внимание, что если вы настроите любой HA явно, он отменит все остальные значения по умолчанию.
Показать ещё 6 комментариев
68

У меня была такая же проблема, с последним Spring 4.1.1 и далее вам нужно добавить следующие jars в 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>

также убедитесь, что у вас есть следующая банда:

<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, неприемлемый в соответствии с запросом "accept" Заголовки

  • 0
    Отлично работает для Spring MVC 4.1.4.RELEASE
  • 0
    Этот ответ является версией, отвечающей Maven, и он работает превосходно! Maven исключения могут быть более ясными о том, что на самом деле происходит под капотом.
Показать ещё 8 комментариев
15

Есть еще один случай, когда этот статус будет возвращен: если планшет Jackson не может понять, как сериализовать ваш bean. Например, если у вас есть два метода доступа для одного и того же логического свойства, isFoo() и getFoo().

Что происходит в том, что Spring MappingJackson2HttpMessageConverter вызывает Jackson StdSerializerProvider, чтобы узнать, может ли он преобразовать ваш объект. В нижней части цепочки вызовов StdSerializerProvider._createAndCacheUntypedSerializer выдает сообщение JsonMappingException информативным сообщением. Однако это исключение проглатывается StdSerializerProvider._createAndCacheUntypedSerializer, которое сообщает Spring, что он не может преобразовать объект. После того, как закончились конвертеры, Spring сообщает, что ему не предоставляется заголовок Accept, который он может использовать, что, конечно же, является фиктивным, когда вы даете ему */*.

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

  • 0
    Спасибо вам большое! Я новичок в Spring MVC, и мне было очень трудно понять, как вернуть JSON. Все упоминают отсутствующие аннотации @ResponseBody и зависимости Джексона как причину 406 ошибок. В моем случае оказывается, что мне просто не хватало метода доступа для открытого поля, принадлежащего объекту, который я хотел вернуть как JSON.
  • 0
    Спасибо @kdgregory! Я забыл добавить геттер / сеттер для поля. Добавление их исправило эту проблему.
13

У меня была та же проблема, мой метод контроллера выполняется, но ответ - Ошибка 406. Я отлаживаю AbstractMessageConverterMethodProcessor#writeWithMessageConverters и обнаружил, что метод ContentNegotiationManager#resolveMediaTypes всегда возвращает text/html, который не поддерживается MappingJacksonHttpMessageConverter. Проблема в том, что org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy работает раньше, чем org.springframework.web.accept.HeaderContentNegotiationStrategy, а расширение моего запроса /get-clients.html является причиной моей проблемы с Error 406. Я просто изменил URL запроса на /get-clients.

  • 0
    Привет atott, у меня та же проблема, и ваш совет по изменению расширения запроса решил мою проблему. Большое спасибо за то, что поделились своим решением!
  • 0
    В моем случае это был идентификатор пути покоя с расширением (в тесте), который вызвал 406 по той же причине, в то время как нормальный контроллер работает (даже если вы использовали расширение в идентификаторе пути покоя).
9

Убедитесь, что в пути класса присутствуют следующие 2 jar.

Если какой-либо из них или оба пропали без вести, эта ошибка появится.

jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar
  • 0
    Благодарю. Я решил эту проблему с вашим ответом!
  • 2
    Это не работает для меня
5

Наконец нашел ответ отсюда:

Отображение ненадежных запросов ajax на spring

Я цитирую:

@Аннотации RequestBody/@ResponseBody не используют обычные разрешения, они используют собственные HttpMessageConverters. Чтобы использовать эти аннотации, вы должны настроить эти конвертеры в AnnotationMethodHandlerAdapter, как описано в ссылке (вам, вероятно, нужен MappingJacksonHttpMessageConverter).

3

Проверьте <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

2
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-base</artifactId>
    <version>2.6.3</version>
</dependency>
  • 2
    Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
1

Вероятно, никто не прокручивается так далеко, но ни один из вышеперечисленных решений не исправил это для меня, но все мои методы получения информации public.

Я оставил свою видимость на получателе в частном кабинете; Джексон решил, что не может найти их и взорвать. (Использование @JsonAutoDetect(getterVisibility=NON_PRIVATE) только частично зафиксировало его.

  • 0
    Это была именно моя проблема. Я сменил сеттеров с публичных на защищенные, и Джексон перестал работать.
1

Весна 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, согласно конфигурации по умолчанию favorPathExtension устанавливается как истина, из-за этого, если у uri запроса есть какие-либо правильные расширения, такие как .htm spring, приоритет будет для расширения. На шаге 2 я добавил компонент contentNegotiationManager, чтобы переопределить это.

1

Как указано @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>

Вот как я наконец решил проблему.

1

У меня была такая же проблема, потому что у меня отсутствовала аннотация @EnableMvc. (Вся моя конфигурация spring основана на аннотации, эквивалент XML будет mvc: аннотация)

1

В контроллере не должно быть аннотации тела ответа на тип возврата, а не метод, например:

@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 установлены правильно.

В другом примечании, я считаю, что обработка spring json довольно проблематична. Это было легче, когда я все это делал сам, используя строки, и GSON.

  • 0
    Размещение @ResponseBody не должно иметь значения ... Я посмотрю на GSON ... но все же хотел бы, чтобы этот JSON работал, если это возможно.
0

Убедитесь, что отправленный объект (в данном случае Weather) содержит getter/setter

0

Это ответ обновления для 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

Надеюсь, это будет полезно для тех, кто использует последнюю весеннюю версию.

0

проверить эту тему. spring mvc restcontroller return json string p/s: вы должны добавить конфигурацию сопоставления son 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()); }

0
<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, помогите вам это сделать.

0

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

Сначала я проверил, что все зависимости находятся на месте, как было предложено @bekur затем я проверил запрос/ответ, который отправляется от клиентов на сервер, все заголовки были установлены надлежащим образом в JQuery. Затем я проверил RequestMappingHandlerAdapter MessageConverters, и все 7 из них были на месте, я действительно начал ненавидеть Spring! Затем я обновился с Spring 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

0

В других случаях очевидных проблем у меня был другой, который я не мог исправить независимо от включения всех возможных 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>
0

Отметьте, как @joyfun сделал для правильной версии jackson, но также проверьте наши заголовки... Принять/не может быть передано клиентом... используйте firebug или эквивалент, чтобы проверить, действительно ли отправляется ваш запрос на получение. Я думаю, что атрибут headers аннотации/может/проверять литералы, хотя я не уверен на 100%.

  • 0
    Я добавил заголовки из firebug в основной пост. Они в порядке?
0

убедитесь, что у вас есть правильная версия jackson в вашем пути к классу

  • 0
    Я добавил jackson-all-1.8.5.jar в папку WEB-INF/lib , но проблема все еще та же: /
-4

Вы можете удалить элемент заголовков в @RequestMapping и попробовать..

Как


@RequestMapping(value="/getTemperature/{id}", method = RequestMethod.GET)

Я предполагаю, что spring делает "содержит проверку", а не точное соответствие для заголовков accept. Но все же стоит попробовать удалить элемент заголовков и проверить.

  • 0
    Я удалил, но все же ошибка. Кстати, когда я смотрю журнал weatherService.getCurrentWeather(id); , а затем запрос с этим был weatherService.getCurrentWeather(id); "активировано" ... так что-то работает ... возможно ли, что появляется 406 и Hibernate SQL select работает одновременно?
  • 0
    Пожалуйста, попробуйте это, оно должно работать. Добавьте эту аннотацию на контроллер @RequestMapping (method = RequestMethod.GET, headers = {"Accept = text / xml, application / json"})

Ещё вопросы

Сообщество Overcoder
Наверх
Меню