ชนิดเนื้อหา 'application / x-www-form-urlencoded; charset = UTF-8' ไม่รองรับ @RequestBody MultiValueMap


100

ตามคำตอบสำหรับปัญหาเกี่ยวกับ 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 หรืออะไรก็ตามที่คุณใช้)
Nikolay Rusev

ผมมีปัญหาเดียวกัน. ในกรณีของฉันฉันใช้ jquery ajax เพื่อโพสต์ข้อมูลและข้อมูลคือJSON.stringify({"ordersToDownload":"00417002"}
Arashsoft

นี่คือรหัสที่ฉันใช้:$.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) })
Arashsoft

ตรวจสอบคำตอบของฉันป้อนคำอธิบายลิงก์ที่นี่
Eshiett Oto-obong

คำตอบ:


130

ปัญหาคือเมื่อเราใช้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 ที่มีแอปพลิเคชันประเภทเนื้อหา / x-www-form-urlencoded ไม่ทำงานใน Spring


ขอขอบคุณ! แก้ปัญหา ตอนนี้ฉันสงสัยว่าเราจะลบอย่างชัดเจนได้ application/x-www-form-urlencodedอย่างไร?
kholofelo Maloma

1
ไม่จำเป็น @kholofeloMaloma
Douglas Ribeiro

1
หากใครสงสัยว่าเหตุใดจึงใช้งานได้โดยไม่มีคำอธิบายประกอบดูเหมือนว่า 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 ของฉันได้ไหม
Osama Al-Banna

9

ในฤดูใบไม้ผลิ 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

3

เพียงแค่ลบ@RequestBodyคำอธิบายประกอบก็สามารถแก้ปัญหาได้ (ทดสอบกับ Spring Boot 2):

@RestController
public class MyController {

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

2

ฉันเขียนเกี่ยวกับทางเลือกในคำตอบ StackOverflowนี้

ที่นั่นฉันเขียนทีละขั้นตอนอธิบายด้วยรหัส วิธีสั้น ๆ :

ขั้นแรก : เขียนวัตถุ

ประการที่สอง : สร้างตัวแปลงเพื่อทำแผนที่โมเดลที่ขยาย AbstractHttpMessageConverter

ประการที่สาม : บอกให้สปริงใช้ตัวแปลงนี้โดยใช้คลาส WebMvcConfigurer. ซึ่งแทนที่เมธอด configMessageConverters

ประการที่สี่และขั้นสุดท้าย: การใช้การตั้งค่าการใช้งานนี้ในการทำแผนที่ภายในตัวควบคุมของคุณจะใช้ = 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 {
    ...
}

วิธีนั้นเหมาะกับฉัน


0

คุณสามารถลองเปิดการรองรับในตัวแปลงของสปริง

@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // add converter suport Content-Type: 'application/x-www-form-urlencoded'
        converters.stream()
                .filter(AllEncompassingFormHttpMessageConverter.class::isInstance)
                .map(AllEncompassingFormHttpMessageConverter.class::cast)
                .findFirst()
                .ifPresent(converter -> converter.addSupportedMediaTypes(MediaType.APPLICATION_FORM_URLENCODED_VALUE));
    }

}


0

@RequestBody MultiValueMap paramMap

ในที่นี้ลบคำอธิบายประกอบ @RequestBody ออก

@RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount(@RequestBody LogingData user){
    logingService.save(user);
    return "login";
}




@RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount( LogingData user){
    logingService.save(user);
    return "login";
} 

เช่นนั้น


แม้ว่ารหัสนี้อาจช่วยแก้ปัญหาได้รวมถึงคำอธิบายว่าทำไมจึงแก้ปัญหานี้ได้จะช่วยปรับปรุงคุณภาพของโพสต์ของคุณได้อย่างแท้จริงและอาจส่งผลให้มีการโหวตเพิ่มขึ้น จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตไม่ใช่แค่คนที่ถามตอนนี้ โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายและระบุข้อ จำกัด และสมมติฐานที่ใช้
Yunnosch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.