Jenis konten 'application / x-www-form-urlencoded; charset = UTF-8' tidak didukung untuk @RequestBody MultiValueMap


95

Berdasarkan jawaban untuk masalah dengan x-www-form-urlencoded dengan Spring @Controller

Saya telah menulis metode @Controller di bawah ini

@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");
            }
    }

permintaan yang gagal dengan kesalahan di bawah ini

{
  "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: Jersey jauh lebih ramah, tetapi tidak bisa menggunakannya sekarang karena pembatasan praktis di sini]


Apakah Anda menambahkan konsumsi = {"application / x-www-form-urlencoded"} di @RequestBody?
shiladitya

1
Bagaimana Anda menjalankan permintaan tersebut? tambahkan kode (js, jquery, curl atau apapun yang anda gunakan).
Nikolay Rusev

Saya memiliki masalah yang sama. Dalam kasus saya, saya menggunakan jquery ajax untuk mengirim data dan datanyaJSON.stringify({"ordersToDownload":"00417002"}
Arashsoft

Ini adalah kode yang saya gunakan:$.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) })
Arashsoft

Jawaban:


126

Masalahnya adalah ketika kita menggunakan application / x-www-form-urlencoded , Spring tidak memahaminya sebagai RequestBody. Jadi, jika kita ingin menggunakan ini kita harus menghapus anotasi @RequestBody .

Kemudian coba yang berikut ini:

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

Perhatikan bahwa menghapus anotasi @RequestBody

jawaban : Permintaan posting Http dengan tipe konten application / x-www-form-urlencoded tidak berfungsi di Spring


Terima kasih! Memecahkan masalah. Sekarang saya bertanya-tanya bagaimana kita secara eksplisit menghapus application/x-www-form-urlencoded?
kholofelo Maloma

1
tidak perlu @kholofeloMaloma
Douglas Ribeiro

Jika ada yang bertanya-tanya mengapa ini berfungsi tanpa anotasi apa pun, tampaknya Spring menangani argumen tanpa anotasi apa pun seolah-olah mereka memiliki @ModelAttribute, even though this behaviour is (sadly) not documented. And @ModelAttribute tidak memahami x-www-form-urlencoded
cranphin

public ResponseEntity <?> getToken (MultiValueMap paramMap) IllegalArgumentException: tipe argumen tidak cocok
withoutOne

Terimakasih atas infonya! Sebagai seorang pemula, saya bertanya-tanya apa alasan di balik perilaku aneh kecil Spring ini untuk mengurai muatan dan mengikatnya ke objek?
hafan96

66

Tampaknya sekarang Anda cukup menandai parameter metode dengan @RequestParamdan itu akan melakukan pekerjaan untuk Anda.

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

18

Tambahkan header ke permintaan Anda untuk menyetel tipe konten ke application / json

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

dengan cara ini spring tahu bagaimana mengurai konten.


Anda mungkin juga perlu menambahkan header Terima ke perintah Anda: 'curl -vk -H "Accept: application / json" -H "Content-Type: application / json"' dll.
razvanone

1
dapatkah Anda menjelaskan cara menambahkan pengaturan ini ke formulir HTML saya?
Osama Al-Banna

8

Di Spring 5

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

    // import org.springframework.util.MultiValueMap;

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

Ya, dengan dimasukkannya consumer = MediaType.APPLICATION_FORM_URLENCODED_VALUE dalam pemetaan, Anda berhak mendapatkan lebih banyak poin, Pak! Terima kasih! @RequestParam jahitan diperlukan sekarang untuk mengambil MultiValueMap dari permintaan
NemanjaT

2

Cukup menghapus @RequestBodyanotasi akan menyelesaikan masalah (diuji pada Spring Boot 2):

@RestController
public class MyController {

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

1

Saya menulis tentang alternatif dalam jawaban StackOverflow ini .

Di sana saya menulis langkah demi langkah, menjelaskan dengan kode. Cara singkatnya:

Pertama : tulis sebuah objek

Kedua : buat konverter untuk memetakan model yang memperluas AbstractHttpMessageConverter

Ketiga : beri tahu untuk musim semi gunakan konverter ini yang mengimplementasikan WebMvcConfigurer.class yang menggantikan metode configureMessageConverters

Keempat dan terakhir: menggunakan pengaturan implementasi ini dalam pemetaan di dalam pengontrol Anda, konsumsi = MediaType.APPLICATION_FORM_URLENCODED_VALUE dan @RequestBody di depan objek Anda.

Saya menggunakan boot musim semi 2.


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

Cara itu berhasil untuk saya

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.