POST-Anfrage über RestTemplate in JSON


126

Ich habe kein Beispiel gefunden, wie ich mein Problem lösen kann, deshalb möchte ich Sie um Hilfe bitten. Ich kann keine POST-Anfrage einfach mit dem RestTemplate-Objekt in JSON senden

Jedes Mal, wenn ich bekomme:

org.springframework.web.client.HttpClientErrorException: 415 Nicht unterstützter Medientyp

Ich benutze RestTemplate folgendermaßen:

...
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment", payment, Payment.class);

Was ist meine Schuld?


1
@troyfolger die URL ist nicht mehr gültig
Noremac

Vielen Dank - dieser Link funktioniert ab diesem Zeitpunkt
troyfolger

Um das oben genannte spezifische OP-Problem zu beheben, fehlt Ihnen wahrscheinlich ein HTTP-Header mit dem entsprechenden Inhaltstyp (siehe Antwort von morganw09dev unten).
Troy Follower

Diese Probleme hängen hauptsächlich mit der Server-API-Konfiguration zusammen. Sie testen die Server-API mit einem eigenständigen Client (wie Postman) und replizieren dieselben Header in Ihrer Anfrage. Zumindest in meinem Fall hat das den Trick gemacht.
Linus

1
@ Johnny B, wenn dies beantwortet wurde, markieren Sie bitte die Antwort
Vishal

Antworten:


161

Diese Technik hat bei mir funktioniert:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);

ich hoffe das hilft


3
Bitte erläutern Sie, welche Zeile das Ergebnis der http-Anfrage zurückgeben soll
gstackoverflow

Für mich war es nicht notwendig, Header anzugeben. Ich habe die HttpEntity verwendet, die einen einzelnen Parameter akzeptiert.
Constantino Cronemberger

24
Methode .put()ist void!
Membersound

4
Verwendung von postForEntity(url, entity, String.class)Werken anstelle vonput(url, entity)
Janac Meena

1
@ Kanu, requestJson ist ein gültiger JSON-String oder etwas anderes?
Deva

95

Beim Versuch, einen REST-Endpunkt zu debuggen, ist dieses Problem aufgetreten. Hier ist ein einfaches Beispiel für die Verwendung der RestTemplate-Klasse von Spring, um eine von mir verwendete POST-Anforderung zu erstellen. Ich habe ziemlich lange gebraucht, um Code von verschiedenen Stellen zusammenzusetzen und eine funktionierende Version zu erhalten.

RestTemplate restTemplate = new RestTemplate();

String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);

Der bestimmte JSON-Parser, den mein Restendpunkt verwendet hat, benötigt doppelte Anführungszeichen um Feldnamen. Deshalb habe ich die doppelten Anführungszeichen in meiner requestJson-Zeichenfolge umgangen.



Kann Spring die Nachrichtenkonverter verwenden, um das Java-Objekt automatisch in json zu konvertieren, wie dies in der Restful API mit RestTemplate der Fall war?
Herbst

1
Das Festlegen des Medientyps auf APPLICATION_JSON ist der Schlüssel zur Behebung des Problems.
Pete T

Ich habe mein Problem mit HttpEntity <String> entity = new HttpEntity <String> (requestJson, Header) behoben. diese Linie
Ved Prakash

76

Ich habe die Restvorlage mit JSONObjects wie folgt verwendet:

// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);

// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);

// send request and parse result
ResponseEntity<String> loginResponse = restTemplate
  .exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK) {
  JSONObject userJson = new JSONObject(loginResponse.getBody());
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
  // nono... bad credentials
}

Vielen Dank - die JSONObject toString-Methode war nützlich für mich und hat mir geholfen, meinen JSONString genau zu machen.
Simon

1
Wie entwickelt man den obigen Code dafür: curl -vvv -X POST " localhost: 8080 / SillyService_SRC / oauth /… "?
Pra_A

@Mikael Lepistö Wie kann ich diese Parameter von json am Serverende abrufen?
KJEjava48

@ KJEjava48 Ich verstehe nicht, was du meinst ... das ist serverseitiger Code in der Antwort. Wenn Sie überlegen, wie Sie die JSON-Antwort analysieren können, hängt dies vom verwendeten Framework ab.
Mikael Lepistö

@ MikaelLepistö Ich meine, wie man json Antwort am anderen Ende analysiert, einschließlich wie man die Antwort in Java empfängt? Sie haben nur den Code für ein Ende (dh Server-Seite) gepostet.
KJEjava48

13

Wie hier angegeben , müssen Sie ein messageConverterfür hinzufügenMappingJacksonHttpMessageConverter


9

Wenn Sie Spring 3.0 verwenden, können Sie die Ausnahme org.springframework.web.client.HttpClientErrorException: 415 Ausnahme für nicht unterstützte Medientypen auf einfache Weise vermeiden, indem Sie die Jackson-JAR-Dateien in Ihren Klassenpfad aufnehmen und das mvc:annotation-drivenKonfigurationselement verwenden. Wie hier angegeben .

Ich habe mir die Haare ausgezogen, um herauszufinden, warum die mvc-ajax- App ohne spezielle Konfiguration für das funktioniert MappingJacksonHttpMessageConverter. Wenn Sie den Artikel lesen, den ich oben eng verlinkt habe:

Unter der Abdeckung delegiert Spring MVC an einen HttpMessageConverter, um die Serialisierung durchzuführen. In diesem Fall ruft Spring MVC einen MappingJacksonHttpMessageConverter auf, der auf dem Jackson JSON-Prozessor basiert. Diese Implementierung wird automatisch aktiviert, wenn Sie das mvc: annotation-gesteuerte Konfigurationselement mit Jackson in Ihrem Klassenpfad verwenden .


7

Der Fehler "415 Nicht unterstützter Medientyp" weist darauf hin, dass der Server Ihre POST-Anforderung nicht akzeptiert. Ihre Anfrage ist absolut in Ordnung, es ist der Server, der falsch konfiguriert ist.

MappingJacksonHttpMessageConvertersetzt den Header für application/jsonden Anfrageinhaltstyp automatisch auf , und ich vermute, dass Ihr Server dies ablehnt. Sie haben uns jedoch nichts über Ihr Server-Setup erzählt, daher kann ich Sie dazu nicht wirklich beraten.


7

Ich mache das so und es funktioniert.

HttpHeaders headers = createHttpHeaders(map);
public HttpHeaders createHttpHeaders(Map<String, String> map)
{   
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    for (Entry<String, String> entry : map.entrySet()) {
        headers.add(entry.getKey(),entry.getValue());
    }
    return headers;
}

// Überschriften hier übergeben

 String requestJson = "{ // Construct your JSON here }";
logger.info("Request JSON ="+requestJson);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
logger.info("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
logger.info("Response ="+response.getBody());

Hoffe das hilft


4

Ich habe dieses Problem bekommen und verwende Spring's RestTemplate auf dem Client und Spring Web auf dem Server. Beide APIs weisen eine sehr schlechte Fehlerberichterstattung auf, was ihre Entwicklung äußerst schwierig macht.

Nachdem ich viele Stunden lang alle möglichen Experimente ausprobiert hatte, stellte ich fest, dass das Problem durch die Übergabe einer Nullreferenz für den POST-Body anstelle der erwarteten Liste verursacht wurde. Ich gehe davon aus, dass RestTemplate den Inhaltstyp nicht aus einem Nullobjekt ermitteln kann, sich aber nicht darüber beschwert. Nachdem ich die richtigen Header hinzugefügt hatte, bekam ich im Frühjahr eine andere serverseitige Ausnahme, bevor ich meine Dienstmethode eingab.

Das Update bestand darin, eine leere Liste vom Client anstelle von null zu übergeben. Es sind keine Header erforderlich, da der Standardinhaltstyp für Nicht-Null-Objekte verwendet wird.


3

Dieser Code funktioniert für mich;

RestTemplate restTemplate = new RestTemplate();
Payment payment = new Payment("Aa4bhs");
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("payment", payment);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headerObject);

Payment res = restTemplate.postForObject(url, httpEntity, Payment.class);

Ich benutze einen sehr ähnlichen Ansatz und es hat bei mir NICHT funktioniert. Aus irgendeinem Grund wird mein Äquivalent Ihrer 'Karte' nicht in json konvertiert oder als ausgehender Text aufgenommen, dh der Zieldienst sieht KEINE Nutzdaten.
Abdel

2

Wenn Sie die Antwort nicht verarbeiten möchten

private RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(serviceURL, request, Void.class);

Wenn Sie eine Antwort auf den Prozess benötigen

String result = restTemplate.postForObject(url, entity, String.class);

0

Bei mir ist bei diesem Setup ein Fehler aufgetreten:

AndroidAnnotations Spring Android RestTemplate Module und ...

GsonHttpMessageConverter

Android-Annotationen haben einige Probleme damit, eine POSTAnforderung ohne Parameter zu generieren . Einfach Parameter new Object()löste es für mich.


0

Warum härter arbeiten als nötig? postForEntityakzeptiert ein einfaches MapObjekt als Eingabe. Das Folgende funktioniert gut für mich, wenn ich im Frühjahr Tests für einen bestimmten REST-Endpunkt schreibe. Ich glaube, es ist die einfachste Möglichkeit, im Frühjahr eine JSON-POST-Anfrage zu stellen:

@Test
public void shouldLoginSuccessfully() {
  // 'restTemplate' below has been @Autowired prior to this
  Map map = new HashMap<String, String>();
  map.put("username", "bob123");
  map.put("password", "myP@ssw0rd");
  ResponseEntity<Void> resp = restTemplate.postForEntity(
      "http://localhost:8000/login",
      map,
      Void.class);
  assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
}

0

Wenn Sie den JSON nicht selbst zuordnen möchten, können Sie dies wie folgt tun:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
ResponseEntity<String> result = restTemplate.postForEntity(uri, yourObject, String.class);

0

Ich habe im Frühjahr Folgendes versucht:

ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
public Map<String, Object> processResponse(String urlendpoint)
{
    try{
    
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //reqobj
        JSONObject request = new JSONObject();
        request.put("username", name);
        //Or Hashmap 
        Map<String, Object> reqbody =  new HashMap<>();
        reqbody.put("username",username);
        Gson gson = new Gson();//mvn plugin to convert map to String
        HttpEntity<String> entity = new HttpEntity<>( gson.toJson(reqbody), headers);
        ResponseEntity<Map<String, Object>> response = resttemplate.exchange(urlendpoint, HttpMethod.POST, entity, typeRef);//example of post req with json as request payload
        if(Integer.parseInt(response.getStatusCode().toString()) == HttpURLConnection.HTTP_OK)
        {
            Map<String, Object>  responsedetails = response.getBody();
            System.out.println(responsedetails);//whole json response as map object
            return responsedetails;
        }
    } catch (Exception e) {
        // TODO: handle exception
        System.err.println(e);
    }
    return null;
}
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.