Тип контента 'application / x-www-form-urlencoded; charset = UTF-8' не поддерживается для @RequestBody MultiValueMap

95

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

Сомасундарам Секар
источник
Вы добавили consumes = {"application / x-www-form-urlencoded"} в @RequestBody?
shiladitya
1
Как вы выполнили запрос? добавьте код (js, jquery, curl или что угодно, что вы используете).
Николай Русев
У меня такая же проблема. В моем случае я использую jquery ajax для публикации данных, и данныеJSON.stringify({"ordersToDownload":"00417002"}
Arashsoft
Это код, который я использую:$.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) })
Arashsoft
Проверьте мой ответ, введите описание ссылки здесь
Eshiett Oto-obong

Ответы:

126

Проблема в том, что когда мы используем 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 не работает в Spring

Дуглас Рибейро
источник
Спасибо! Решает проблему. Теперь мне интересно, как нам явно удалить application/x-www-form-urlencoded?
Холофело Малома
1
это не обязательно @kholofeloMaloma
Дуглас Рибейро
Если кому-то интересно, почему это работает без какой-либо аннотации, похоже, Spring обрабатывает любые @ModelAttribute, even though this behaviour is (sadly) not documented. And неаннотированные аргументы, как если бы у них есть @ModelAttribute, действительно понимающий x-www-form-urlencoded
Cranphin
public ResponseEntity <?> getToken (MultiValueMap paramMap) IllegalArgumentException: несоответствие типа аргумента
без
Спасибо за информацию! Как новичку, мне интересно, в чем причина этого небольшого странного поведения Spring для анализа полезной нагрузки и привязки ее к объекту?
hafan96
66

Кажется, теперь вы можете просто пометить параметр метода, @RequestParamи он сделает всю работу за вас.

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam Map<String, String> body ) {
  //work with Map
}
Scadge
источник
18

Добавьте заголовок в свой запрос, чтобы установить тип содержимого как application / json

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

таким образом Spring знает, как анализировать контент.

Агустин Альмонте
источник
Возможно, вам также потребуется добавить заголовок 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");
}
Эдгардо Дженини
источник
Да, с включением в отображение consumer = 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

Третье : скажите Spring использовать этот конвертер, реализующий WebMvcConfigurer.class, переопределяющий метод configureMessageConverters

Четвертое и последнее: используя этот параметр реализации в сопоставлении внутри вашего контроллера, consumes = 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 {
    ...
}

Этот способ работает для меня

Фернандо Сикейра
источник