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]

Somasundaram Sekar
sumber
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
Periksa jawaban saya, masukkan deskripsi tautan di sini
Eshiett Oto-obong

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

Douglas Ribeiro
sumber
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
}
Scadge
sumber
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.

Agustin Almonte
sumber
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");
}
Edgardo Genini
sumber
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 ...
    }
}
Hamid Mohayeji
sumber
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.

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

Cara itu berhasil untuk saya

Fernando Siqueira
sumber