wake-up-neo.net

Wie extrahiere ich den HTTP-Statuscode aus dem RestTemplate-Aufruf in eine URL?

Ich benutze RestTemplate, um einen HTTP-Aufruf an unseren Service auszuführen, der eine einfache JSON-Antwort zurückgibt. Ich muss das JSON überhaupt nicht analysieren. Ich muss nur zurückgeben, was ich von diesem Service bekomme.

Also ordne ich das auf String.class zu und gebe den tatsächlichen JSON response als String zurück.

RestTemplate restTemplate = new RestTemplate();

String response = restTemplate.getForObject(url, String.class);

return response;

Nun ist die Frage - 

Ich versuche, HTTP Status codes nach dem Aufrufen der URL zu extrahieren. Wie kann ich HTTP-Statuscode aus dem obigen Code extrahieren? Muss ich daran etwas ändern, wie ich es derzeit mache?

Update: -

Das habe ich ausprobiert und ich kann auch die Antwort und den Statuscode zurückerhalten. Muss ich aber immer HttpHeaders und Entity wie unten angegeben einstellen?

    RestTemplate restTemplate = new RestTemplate();     

    //and do I need this JSON media type for my use case?
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    //set my entity
    HttpEntity<Object> entity = new HttpEntity<Object>(headers);

    ResponseEntity<String> out = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);

    System.out.println(out.getBody());
    System.out.println(out.getStatusCode());

Ein paar Fragen - Muss ich MediaType.APPLICATION_JSON haben, da ich gerade eine URL anrufe, die eine Antwort zurücksendet, kann entweder JSON oder XML oder ein einfacher String zurückgegeben werden.

28
john

Verwenden Sie die Methoden RestTemplate#exchange(..) , die eine ResponseEntity zurückgeben. Dadurch haben Sie Zugriff auf die Statuszeile und die Kopfzeilen (und natürlich auf den Körper).

26

Wenn Sie die Nice-Abstraktion nicht mit RestTemplate.get/postForObject...-Methoden hinter mir lassen wollen und nicht gerne mit den Boilerplate-Dingen herumarbeiten, die bei der Verwendung von RestTemplate.exchange... (Request- und ResponseEntity, HttpHeaders usw.) erforderlich sind, gibt es eine weitere Option, um darauf zuzugreifen die HttpStatus-Codes.

Umgeben Sie einfach den üblichen RestTemplate.get/postForObject... mit einem try/catch für org.springframework.web.client.HttpClientErrorException und org.springframework.web.client.HttpServerErrorException, wie in diesem Beispiel:

try {
    return restTemplate.postForObject("http://your.url.here", "YourRequestObjectForPostBodyHere", YourResponse.class);

} catch (HttpClientErrorException | HttpServerErrorException httpClientOrServerExc) {

    if(HttpStatus.NOT_FOUND.equals(httpClientOrServerExc.getStatusCode())) {
      // your handling of "NOT FOUND" here  
      // e.g. throw new RuntimeException("Your Error Message here", httpClientOrServerExc);
    }
    else {
      // your handling of other errors here
}

Der org.springframework.web.client.HttpServerErrorException wird hier für die Fehler mit einem 50x hinzugefügt.

Jetzt können Sie ganz einfach auf alle gewünschten StatusCodes reagieren - mit Ausnahme des entsprechenden, der Ihrer HTTP-Methode entspricht - wie GET und 200, die nicht als Ausnahme behandelt werden, da es sich um die entsprechende handelt. Dies sollte jedoch einfach sein, wenn Sie RESTful-Dienste implementieren/in Anspruch nehmen :) 

6
jonashackt
private RestTemplate restTemplate = new RestTemplate();

ResponseEntity<String> response = restTemplate.exchange(url,HttpMethod.GET, requestEntity,String.class);

antwort enthält 'body', 'headers' und 'statusCode'

um statusCode zu erhalten: response.getStatusCode ();

1
santosh kumar

Es reicht mir, so viel Code zu schreiben HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode();

0
Subha Mukherjee

Es kann ein paar kniffligere Anwendungsfälle geben, in die jemand hineinkommt (wie ich). Folgendes berücksichtigen:

Unterstützen eines Page-Objekts, um es mit RestTemplate und ParameterizedTypeReference zu verwenden:

RestPageResponse:

import Java.util.ArrayList;
import Java.util.List;

import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

public class RestResponsePage<T> extends PageImpl<T>{

  private static final long serialVersionUID = 3248189030448292002L;

  public RestResponsePage(List<T> content, Pageable pageable, long total) {
    super(content, pageable, total);
  }

  public RestResponsePage(List<T> content) {
    super(content);
  }

  public RestResponsePage() {
    super(new ArrayList<T>());
  }

} 

Die Verwendung von ParameterizedTypeReference ergibt folgendes:

ParameterizedTypeReference<RestResponsePage<MyObject>> responseType = 
new ParameterizedTypeReference<RestResponsePage<MyObject>>() {};
HttpEntity<RestResponsePage<MyObject>> response = restTemplate.exchange(oauthUrl, HttpMethod.GET, entity, responseType);

Aufruf von #exchange :

HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            HttpEntity<?> entity = new HttpEntity<>(headers);

response = restTemplate.exchange("localhost:8080/example", HttpMethod.GET, entity, responseType);

Jetzt ist hier der "knifflige" Teil. 

Der Versuch, die Variable getStatusCode von exchange aufzurufen, wird unmöglich sein, da der Compiler den beabsichtigten Typ von response leider nicht kennt. 

Das liegt daran, dass Generics über die Typlöschung implementiert werden, die alle Informationen zu generischen Typen während der Kompilierung entfernt. (Weitere Informationen - Quelle)

((ResponseEntity<RestResponsePage<MyObject>>) response).getStatusCode()

In diesem Fall müssen Sie die Variable explizit in die gewünschte Klasse umwandeln, um die statusCode (und/oder andere Attribute) zu erhalten!

exchange (...) funktioniert, aber wenn Sie weniger Code möchten, können Sie verwenden

org.springframework.boot.test.web.client.TestRestTemplate.getForEntity (...)

dies gibt eine Entität zurück, die StatusCode enthält. Ändern Sie Ihren Beispielcode in:

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
HttpStatus statusCode = response.getStatusCode();

Zum Testen können Sie dieses Snippet aus meinem Unit-Test verwenden:

ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertResponseHeaderIsCorrect(response, HttpStatus.OK);

/**
 * Test the basics of the response, non-null, status expected, etc...
 */
private void assertResponseHeaderIsCorrect(ResponseEntity<String> response, HttpStatus expectedStatus) {
    assertThat(response).isNotNull();
    assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8);
    assertThat(response.getStatusCode()).isEqualTo(expectedStatus);
}
0
LazR

Wenn Sie den gesamten HTTPStatus einer RestTemplate einschließlich 4XX und 5XX möchten, müssen Sie der restTemplate einen ResponseErrorHandler bereitstellen, da der Standardhandler im Fall von 4XX oder 5XX eine Ausnahme auslöst

Wir könnten so etwas machen:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
    @Override
    public boolean hasError(HttpStatus statusCode) {
        return false;
    }
});

ResponseEntity<YourResponse> responseEntity =
    restTemplate.getForEntity("http://your.url.here", YourResponse.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.XXXX);
0
Matthieu Gabin