Der Inhaltstyp 'application / x-www-form-urlencoded; charset = UTF-8' wird für @RequestBody MultiValueMap nicht unterstützt


90

Basierend auf der Antwort auf ein Problem mit x-www-form-urlencoded mit Spring @Controller

Ich habe die folgende @ Controller-Methode geschrieben

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

Die Anfrage, auf die mit dem folgenden Fehler fehlschlägt

{
  "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 war weitaus freundlicher, konnte es aber angesichts der praktischen Einschränkungen hier nicht verwenden]


Haben Sie in @RequestBody verbrauchen = {"application / x-www-form-urlencoded"} hinzugefügt?
— Shiladitya

1
Wie haben Sie die Anfrage ausgeführt? Fügen Sie den Code von (js, jquery, curl oder was auch immer Sie verwenden) hinzu.
— Nikolay Rusev

Ich habe das gleiche Problem. In meinem Fall benutze ich jquery ajax, um die Daten zu posten und die Daten sindJSON.stringify({"ordersToDownload":"00417002"}
— Arashsoft

Dies ist der Code, den ich benutze:$.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) })
— Arashsoft

Überprüfen Sie meine Antwort aus geben Sie
— Linkbeschreibung

Antworten:


119

Das Problem ist, dass Spring es bei Verwendung von application / x-www-form-urlencoded nicht als RequestBody versteht. Wenn wir dies verwenden möchten, müssen wir die Annotation @RequestBody entfernen .

Versuchen Sie dann Folgendes:

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

Beachten Sie, dass die Anmerkung @RequestBody entfernt wurde

Antwort : HTTP-Post-Anfrage mit Inhaltstyp application / x-www-form-urlencoded funktioniert im Frühjahr nicht


Danke dir! Löst das Problem. Jetzt frage ich mich, wie wir das explizit entfernen application/x-www-form-urlencoded?
— Kholofelo Maloma

1
es ist nicht notwendig @kholofeloMaloma
— Douglas Ribeiro

Wenn sich jemand gefragt hat, warum dies ohne Annotation funktioniert, scheint Spring alle nicht annotierten Argumente so zu behandeln, als ob sie @ModelAttribute, even though this behaviour is (sadly) not documented. And @ModelAttribute haben. X-www-form-urlencoded
— cranphin

public ResponseEntity <?> getToken (MultiValueMap paramMap) IllegalArgumentException: Nicht übereinstimmender Argumenttyp
— Ein

Danke für die Information! Als Neuling frage ich mich, was der Grund für dieses seltsame Verhalten von Spring ist, die Nutzlast zu analysieren und an ein Objekt zu binden.
— hafan96

66

Es scheint, dass Sie jetzt nur den Methodenparameter mit markieren können @RequestParamund er die Arbeit für Sie erledigt.

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

18

Fügen Sie Ihrer Anfrage einen Header hinzu, um den Inhaltstyp auf application / json festzulegen

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

Auf diese Weise weiß Spring, wie man den Inhalt analysiert.


Möglicherweise müssen Sie Ihrem Befehl auch einen Accept-Header hinzufügen: 'curl -vk -H "Accept: application / json" -H "Inhaltstyp: application / json"' usw.
— razvanone

1
Können Sie bitte erklären, wie ich diese Einstellung zu meinem HTML-Formular hinzufüge?
— Osama Al-Banna

6

Im Frühjahr 5

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

    // import org.springframework.util.MultiValueMap;

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

Ja, mit der Einbeziehung von consumer = MediaType.APPLICATION_FORM_URLENCODED_VALUE in das Mapping verdienen Sie mehr Punkte, Sir! Danke! @RequestParam-Nähte werden jetzt benötigt, um MultiValueMap von der Anfrage
— abzuholen

2

Das einfache Entfernen von @RequestBodyAnmerkungen löst das Problem (getestet auf Spring Boot 2):

@RestController
public class MyController {

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

1

Ich habe in dieser StackOverflow-Antwort über eine Alternative geschrieben .

Dort schrieb ich Schritt für Schritt und erklärte mit Code. Der kurze Weg:

Erstens : Schreiben Sie ein Objekt

Zweitens : Erstellen Sie einen Konverter für die Zuordnung des Modells, das den AbstractHttpMessageConverter erweitert

Drittens : Weisen Sie Spring an, diesen Konverter zu verwenden, der eine WebMvcConfigurer.class implementiert, die die configureMessageConverters-Methode überschreibt

Viertens und endgültig: Wenn Sie diese Implementierungseinstellung in der Zuordnung in Ihrem Controller verwenden, verbrauchen Sie = MediaType.APPLICATION_FORM_URLENCODED_VALUE und @RequestBody vor Ihrem Objekt.

Ich benutze Spring Boot 2.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.