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.