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]

Somasundaram Sekar
quelle
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

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

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

Marco Blos
quelle