Тип вмісту 'application / x-www-form-urlencoded; charset = UTF-8' не підтримується для @RequestBody MultiValueMap


94

На основі відповіді на проблему з x-www-form-urlencoded з Spring @Controller

Я написав нижченаведений метод @Controller

@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST
            , produces = {"application/json", "application/xml"}
            ,  consumes = {"application/x-www-form-urlencoded"}
    )
     public
        @ResponseBody
        Representation authenticate(@PathVariable("email") String anEmailAddress,
                                    @RequestBody MultiValueMap paramMap)
                throws Exception {


            if(paramMap == null || paramMap.get("password") == null) {
                throw new IllegalArgumentException("Password not provided");
            }
    }

запит, на який не вдається виконати помилку нижче

{
  "timestamp": 1447911866786,
  "status": 415,
  "error": "Unsupported Media Type",
  "exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
  "message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
  "path": "/users/usermail%40gmail.com/authenticate"
}

[PS: Джерсі був набагато більш доброзичливим, але зараз не міг ним скористатися, враховуючи практичні обмеження тут]


Ви додали споживання = {"application / x-www-form-urlencoded"} в @RequestBody?
шиладітя

1
Як ви виконали запит? додайте код (js, jquery, curl або що завгодно).
Микола Русєв

У мене така сама проблема. У моєму випадку я використовую jquery ajax для розміщення даних, а дані такіJSON.stringify({"ordersToDownload":"00417002"}
Arashsoft

Це код, яким я користуюся:$.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) })
Arashsoft

Відповіді:


125

Проблема полягає в тому, що коли ми використовуємо application / x-www-form-urlencoded , Spring не розуміє це як RequestBody. Отже, якщо ми хочемо використовувати це, ми повинні видалити анотацію @RequestBody .

Потім спробуйте наступне:

@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, 
        produces = {MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public @ResponseBody  Representation authenticate(@PathVariable("email") String anEmailAddress, MultiValueMap paramMap) throws Exception {
   if(paramMap == null && paramMap.get("password") == null) {
        throw new IllegalArgumentException("Password not provided");
    }
    return null;
}

Зверніть увагу, що анотацію @RequestBody видалено

відповідь : Запит Http Post із типом вмісту application / x-www-form-urlencoded не працює навесні


Дякую! Вирішує проблему. Тепер мені цікаво, як нам явно видалити application/x-www-form-urlencoded?
Холофело Малома

1
це не потрібно @kholofeloMaloma
Douglas Ribeiro

Якщо хтось замислювався над тим, чому це працює без будь-яких анотацій, здається, Spring обробляє будь-які не анотовані аргументи так, ніби вони мають @ModelAttribute, even though this behaviour is (sadly) not documented. And @ModelAttribute розуміє x-www-form-urlencoded
cranphin

public ResponseEntity <?> getToken (MultiValueMap paramMap) IllegalArgumentException: невідповідність типу аргументу
withoutOne

Дякую за інформацію! Як новачкові, мені цікаво, в чому причина цієї маленької дивної поведінки Spring для синтаксичного аналізу корисного навантаження та прив'язки його до об'єкта?
hafan96

66

Здається, що тепер ви можете просто позначити параметр методу за допомогою, @RequestParamі він зробить роботу за вас.

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam Map<String, String> body ) {
  //work with Map
}

18

Додайте заголовок до вашого запиту, щоб встановити тип вмісту для application / json

curl -H 'Content-Type: application/json' -s -XPOST http://your.domain.com/ -d YOUR_JSON_BODY

таким чином весна знає, як проаналізувати вміст.


Можливо, вам доведеться також додати заголовок Accept до вашої команди: 'curl -vk -H "Accept: application / json" -H "Content-Type: application / json"' тощо
razvanone

1
Ви можете пояснити, як додати це налаштування до моєї HTML-форми?
Усама Аль-Банна

8

Навесні 5

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam MultiValueMap body ) {

    // import org.springframework.util.MultiValueMap;

    String datax = (String) body .getFirst("datax");
}

Так, з включенням споживача = MediaType.APPLICATION_FORM_URLENCODED_VALUE до картографування, ви заслуговуєте на більше балів, сер! Дякую! Шви @RequestParam знадобляться зараз для отримання MultiValueMap із запиту
NemanjaT

2

Просто видалення @RequestBodyанотації вирішує проблему (перевірено на Spring Boot 2):

@RestController
public class MyController {

    @PostMapping
    public void method(@Valid RequestDto dto) {
       // method body ...
    }
}

1

Я писав про альтернативу в цій відповіді StackOverflow .

Там я писав поетапно, пояснюючи кодом. Короткий шлях:

Спочатку : напишіть об’єкт

По-друге : створіть конвертер для відображення моделі, що розширює AbstractHttpMessageConverter

По-третє : скажіть весняному використанню цього перетворювача, що реалізує WebMvcConfigurer.class, який замінює метод configureMessageConverters

Четверте і останнє: використовуючи цей параметр реалізації у відображенні всередині вашого контролера, споживає = MediaType.APPLICATION_FORM_URLENCODED_VALUE та @RequestBody перед вашим об’єктом.

Я використовую пружинне завантаження 2.


0
@PostMapping(path = "/my/endpoint", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception {
    ...
}

Цей спосіб працює для мене

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.