Весняний запит JSON на отримання 406 (не прийнятний)


85

це мій 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)

Заголовки:

Заголовки відповідей

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 було два подібних запитання, я спробував там усі прийняті підказки, але вони, здається, не спрацювали ...

Будь-які пропозиції? Не соромтеся задавати питання ...

Відповіді:


107

406 Не прийнятно

Ресурс, ідентифікований запитом, здатний генерувати лише сутності відповіді, які мають неприйнятні характеристики вмісту відповідно до заголовків accept, надісланих у запиті.

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

Або у вас немає правильної бібліотеки Джексона у вашому шляху до класу, або ви не використовували <mvc:annotation-driven>директиву.

Я успішно відтворив ваш сценарій, і він працював нормально, використовуючи ці дві бібліотеки та жодної headers="Accept=*/*"директиви.

  • jackson-core-asl-1.7.4.jar
  • jackson-mapper-asl-1.7.4.jar

Ні, це не була проблема, перевірте мою відповідь.
Jaanus

Якщо налаштування HttpMessageConverters вирішило вашу проблему вручну, то використання mvc: анотації, керованого анотацією, зробить те саме, що автоматично налаштовує конвертери та HandlerAdapters (HA). Зверніть увагу, що якщо ви явно налаштуєте будь-яку HA, вона скасує всі інші за замовчуванням.
Віллу Сепман,

Хм, що це mvcтам? Я використовував <tx:annotation-driven />і tx isxmlns:tx="http://www.springframework.org/schema/tx"
Jaanus

1
Ви отримали щось на зразок: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">і банки spring-web-3.0.x та spring-webmvc-3.0.x?
Villu Sepman

1
Ах, у мене там не було цього схеми ... але дякую, це мені допомогло Я думав, що tx:annotation-drivenце те саме, що mvc:annotation-driveі щось.
Jaanus

74

У мене була та ж проблема, з останньою весною 4.1.1 і далі вам потрібно додати наступні банки до 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 Пружина MVC Json, не прийнятна відповідно до запитів "прийняти" заголовки


Ця відповідь є версією найпопулярнішої версії Maven, і вона працює найкраще! Винятки Maven можуть бути більш зрозумілими щодо того, що насправді відбувається під капотом.
Cotta,

4
Чи можете ви вказати, де це задокументовано в офіційній документації Спрінгс? Звідки хтось може знати, що це проблема?
Adelin

Вам потрібно лише вказати залежності до jackson-databind та jackson-mapper-asl, інші два є транзитивними залежностями і все одно будуть вирішені.
anre

1
Це працювало у мене лише після додавання двох других залежностей. Дякую.
DocWatson,

Вам обов’язково не потрібно і те, і інше. Spring додасть MappingJacksonHttpMessageConverterдля Джексона 1 і MappingJackson2HttpMessageConverterдля Джексона 2. Кожен з них достатньо хороший для серіалізації / десеріалізації JSON. Вам потрібен лише один (перейдіть із Jackson 2, оскільки він більше багатий на функції).
Sotirios Delimanolis

16

Є ще один випадок, коли цей статус буде повернуто: якщо картограф Джексона не може зрозуміти, як серіалізувати ваш боб. Наприклад, якщо у вас є два методи доступу для одного і того ж логічного властивості, isFoo()та getFoo().

Що відбувається, це те, що Spring's MappingJackson2HttpMessageConverter викликає Jackson's StdSerializerProvider, щоб перевірити, чи зможе він перетворити ваш об'єкт. Внизу ланцюжка дзвінків StdSerializerProvider._createAndCacheUntypedSerializerкидає а JsonMappingExceptionз інформативним повідомленням. Однак цей виняток проковтується StdSerializerProvider._createAndCacheUntypedSerializer, що повідомляє Spring, що він не може перетворити об'єкт. Закінчивши перетворювачі, Spring повідомляє, що йому не дано Acceptзаголовок, який він може використовувати, що, звичайно, є фіктивним, коли ви його надаєте */*.

Існує помилка такої поведінки, але вона була закрита, оскільки "не може відтворюватися": метод, який викликається, не заявляє, що може кидати, тому проковтування винятків є, мабуть, відповідним рішенням (так, це був сарказм). На жаль, у Джексона немає реєстрації ... і в кодовій базі є багато коментарів, які бажають цього зробити, тому я підозрюю, що це не єдина прихована помилка.


Дуже дякую! Я новачок у Spring MVC, і мені було дуже важко зрозуміти, як повернути JSON. Усі згадують відсутні причини анотацій @ResponseBody та залежності Джексона як причину 406 помилок. У моєму випадку виявляється, мені просто не вистачало методу доступу для відкритого поля, що належить об’єкту, який я хотів повернути як JSON.
Ентоні Джек,

Дякую @kdgregory! Я забув додати getter / setter для поля. Додавання їх вирішило цю проблему.
Рубенс Маріуццо

16

У мене була та сама проблема, мій метод контролера виконується, але відповідь - помилка 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.


Привіт atott, у мене така сама проблема, і ваша порада щодо зміни розширення запиту вирішила мою проблему. Велике спасибі, що поділились своїм рішенням !!
jherranzm

У моєму випадку це був ідентифікатор шляху відпочинку з розширенням у ньому (у тесті), що спричинило 406 з тієї ж причини, тоді як звичайний контролер працює (навіть якщо ви мали використовувати розширення в ідентифікаторі шляху відпочинку).
Jur_

9

Переконайтеся, що наступні 2 jarє присутніми у шляху до класу.

Якщо будь-який з них або обидва відсутні, ця помилка з’явиться.

jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar

6

Нарешті знайдена відповідь звідси:

Складання спокійних запитів ajax на весну

Я цитую:

Анотації @ RequestBody / @ ResponseBody не використовують звичайні засоби розпізнавання подання, вони використовують свої власні HttpMessageConverters. Для того, щоб використовувати ці анотації, слід налаштувати ці перетворювачі в AnnotationMethodHandlerAdapter, як описано в посиланні (вам, мабуть, потрібен MappingJacksonHttpMessageConverter).


3

Перевірте <mvc:annotation-driven />у dispecherservlet.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
Хоча цей код може відповісти на питання, надання додаткового контексту щодо того, як та / або чому він вирішує проблему, покращило б довгострокове значення відповіді.
Франческо Мензані

2

Напевно, ніхто так далеко не прокручує вниз, але жодне з наведених вище рішень не виправило це для мене, однак усі мої методи отримання publicотримали.

Я залишив свою видимість отримання в приватному пакеті; Джексон вирішив, що не може їх знайти, і підірвав. (Використовуючи @JsonAutoDetect(getterVisibility=NON_PRIVATE)лише частково виправлене.


Це було саме моє питання. Я міняю своїх установників із загальнодоступних на захищених, і Джексон перестав працювати.
JuanMiguel

Ту саму проблему тут я використовував, AbstractMap.SimpleImmutableEntryа потім понизив до AbstractMap.SimpleEntry, все ще не мав кубиків, оскільки в ньому немає сеттера для ключа. Пропав пожо на цьому.
Роберт Бейн,

2

Переконайтесь, що надісланий об’єкт (в даному випадку Погода) містить getter / setter


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

Я б також використав необроблену функцію jquery.ajax та переконався, що contentType та dataType встановлені правильно.

З іншого боку, я вважаю весняну обробку json досить проблематичною. Це було простіше, коли я все це робив сам, використовуючи рядки та GSON.


Розміщення @ResponseBodyне повинно мати значення ... Я розгляну GSON ... але все одно хотів би, щоб цей JSON працював, якщо це можливо.
Jaanus

1

Як згадував @atott .

Якщо ви додали останню версію Джексона у свій 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

Весна 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 встановлюється як true, через це, якщо uri запиту має якісь відповідні розширення, наприклад .htmspring, буде надавати пріоритет розширенню. На кроці 2 я додав компонент contentNegotiationManager, щоб замінити це.


1

У мене була та сама проблема, оскільки мені не вистачало анотації @EnableWebMvc. (Усі мої весняні конфігурації базуються на анотаціях, еквівалент XML буде mvc: керований анотаціями)


0

переконайтеся, що у вас є правильна версія джексона у вашому класі


Я додав jackson-all-1.8.5.jar у свою WEB-INF/libпапку, але все ще та сама проблема: /
Jaanus

0

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


Я додав заголовки від firebug на основний пост. Вони в порядку?
Jaanus

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

У мене була та сама проблема, на жаль, не вирішення тут вирішило мою проблему, оскільки моя проблема була в іншому класі.

Спочатку я перевірив, що всі залежності на місці, як запропонував @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


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

перевірити цю тему. spring mvc restcontroller повертає json рядок p / s: вам слід додати конфігурацію jack son mapping до вашого класу 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

Це відповідь на оновлення для 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

Сподіваюся, це буде корисно для тих, хто використовує останню весняну версію.


-3

Чи можете ви видалити елемент заголовка в @RequestMapping і спробувати ..

Люблю


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

Я думаю, весна робить "містить перевірку", а не точну відповідність для прийнятих заголовків. Але все-таки варто спробувати видалити елемент заголовків і перевірити.


Я видалив, але все-таки помилка. До речі, коли я переглядаю журнал tomcat, тоді запит із цим було weatherService.getCurrentWeather(id);"активовано" ... отже, щось працює ... чи можливо, що з'являється 406 і Hibernate SQL select працює одночасно?
Jaanus

Будь ласка, спробуйте цей, він повинен працювати. Додайте цю анотацію на контролері @RequestMapping (method = RequestMethod.GET, headers = {"Accept = text / xml, application / json"})
сат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.