Przewodnik po RestTemplate

1. Przegląd

W tym samouczku zamierzamy zilustrować szeroki zakres operacji, w których klient Spring REST - RestTemplate - może być używany i dobrze używany.

Po stronie API wszystkich przykładów będziemy tutaj uruchamiać usługę RESTful.

2. Powiadomienie o wycofaniu

Począwszy od Spring Framework 5, obok stosu WebFlux, Spring wprowadził nowego klienta HTTP o nazwie WebClient .

WebClient to nowoczesny, alternatywny klient HTTP dla RestTemplate . Nie tylko zapewnia tradycyjny synchroniczny interfejs API, ale także obsługuje wydajne podejście nieblokujące i asynchroniczne.

To powiedziawszy, jeśli tworzymy nowe aplikacje lub migrujemy starą, dobrym pomysłem jest użycie WebClient . Idąc dalej, RestTemplate zostanie wycofany w przyszłych wersjach.

3. Użyj GET, aby pobrać zasoby

3.1. Uzyskaj zwykły JSON

Zacznijmy prosto i porozmawiajmy o żądaniach GET, z krótkim przykładem wykorzystującym API getForEntity () :

RestTemplate restTemplate = new RestTemplate(); String fooResourceUrl = "//localhost:8080/spring-rest/foos"; ResponseEntity response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class); assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

Zauważ, że mamy pełny dostęp do odpowiedzi HTTP , więc możemy na przykład sprawdzić kod statusu, aby upewnić się, że operacja się powiodła lub pracować z rzeczywistą treścią odpowiedzi:

ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(response.getBody()); JsonNode name = root.path("name"); assertThat(name.asText(), notNullValue());

Pracujemy tutaj z treścią odpowiedzi jako standardowym ciągiem znaków i używamy Jacksona (i struktury węzłów JSON, którą zapewnia Jackson), aby zweryfikować niektóre szczegóły.

3.2. Pobieranie POJO zamiast JSON

Możemy również mapować odpowiedź bezpośrednio na Resource DTO:

public class Foo implements Serializable { private long id; private String name; // standard getters and setters }

Teraz możemy po prostu użyć getForObject API w szablonie:

Foo foo = restTemplate .getForObject(fooResourceUrl + "/1", Foo.class); assertThat(foo.getName(), notNullValue()); assertThat(foo.getId(), is(1L));

4. Użyj HEAD, aby pobrać nagłówki

Przyjrzyjmy się teraz krótko, jak używać HEAD, zanim przejdziemy do bardziej powszechnych metod.

Będziemy używać API headForHeaders () tutaj:

HttpHeaders httpHeaders = restTemplate.headForHeaders(fooResourceUrl); assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON));

5. Użyj POST, aby utworzyć zasób

Aby stworzyć nowy zasób w API, możemy dobrze wykorzystać API postForLocation () , postForObject () lub postForEntity () .

Pierwsza zwraca identyfikator URI nowo utworzonego zasobu, a druga zwraca sam zasób.

5.1. Funkcja API postForObject ()

RestTemplate restTemplate = new RestTemplate(); HttpEntity request = new HttpEntity(new Foo("bar")); Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class); assertThat(foo, notNullValue()); assertThat(foo.getName(), is("bar"));

5.2. Funkcja API postForLocation ()

Podobnie, spójrzmy na operację, która zamiast zwracać pełny zasób, po prostu zwraca lokalizację nowo utworzonego zasobu:

HttpEntity request = new HttpEntity(new Foo("bar")); URI location = restTemplate .postForLocation(fooResourceUrl, request); assertThat(location, notNullValue());

5.3. Wymiany () API

Przyjrzyjmy się, jak wykonać POST z bardziej ogólnym interfejsem API wymiany :

RestTemplate restTemplate = new RestTemplate(); HttpEntity request = new HttpEntity(new Foo("bar")); ResponseEntity response = restTemplate .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); assertThat(response.getStatusCode(), is(HttpStatus.CREATED)); Foo foo = response.getBody(); assertThat(foo, notNullValue()); assertThat(foo.getName(), is("bar")); 

5.4. Prześlij dane formularza

Następnie przyjrzyjmy się, jak przesłać formularz metodą POST.

Najpierw musimy ustawić nagłówek Content-Type na application / x-www-form-urlencoded.

Daje to pewność, że do serwera można wysłać duży ciąg zapytania, zawierający pary nazwa / wartość oddzielone znakiem & :

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

Możemy zawinąć zmienne formularza w LinkedMultiValueMap :

MultiValueMap map= new LinkedMultiValueMap(); map.add("id", "1");

Następnie budujemy żądanie przy użyciu HttpEntity instancji :

HttpEntity
    
      request = new HttpEntity(map, headers);
    

Wreszcie możemy połączyć się z usługą REST, wywołując restTemplate.postForEntity () na Endpoint: / foos / form

ResponseEntity response = restTemplate.postForEntity( fooResourceUrl+"/form", request , String.class); assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

6. Użyj opcji OPCJE, aby uzyskać dozwolone operacje

Następnie szybko przyjrzymy się używaniu żądania OPTIONS i badaniu dozwolonych operacji na określonym identyfikatorze URI przy użyciu tego rodzaju żądania; API to optionsForAllow :

Set optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl); HttpMethod[] supportedMethods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE}; assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));

7. Użyj PUT, aby zaktualizować zasób

Next, we'll start looking at PUT and more specifically the exchange() API for this operation, since the template.put API is pretty straightforward.

7.1. Simple PUT With exchange()

We'll start with a simple PUT operation against the API — and keep in mind that the operation isn't returning a body back to the client:

Foo updatedInstance = new Foo("newName"); updatedInstance.setId(createResponse.getBody().getId()); String resourceUrl = fooResourceUrl + '/' + createResponse.getBody().getId(); HttpEntity requestUpdate = new HttpEntity(updatedInstance, headers); template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);

7.2. PUT With exchange() and a Request Callback

Next, we're going to be using a request callback to issue a PUT.

Let's make sure we prepare the callback, where we can set all the headers we need as well as a request body:

RequestCallback requestCallback(final Foo updatedInstance) { return clientHttpRequest -> { ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(clientHttpRequest.getBody(), updatedInstance); clientHttpRequest.getHeaders().add( HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); clientHttpRequest.getHeaders().add( HttpHeaders.AUTHORIZATION, "Basic " + getBase64EncodedLogPass()); }; }

Next, we create the Resource with a POST request:

ResponseEntity response = restTemplate .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

And then we update the Resource:

Foo updatedInstance = new Foo("newName"); updatedInstance.setId(response.getBody().getId()); String resourceUrl =fooResourceUrl + '/' + response.getBody().getId(); restTemplate.execute( resourceUrl, HttpMethod.PUT, requestCallback(updatedInstance), clientHttpResponse -> null);

8. Use DELETE to Remove a Resource

Aby usunąć istniejący zasób, szybko wykorzystamy interfejs API delete () :

String entityUrl = fooResourceUrl + "/" + existingResource.getId(); restTemplate.delete(entityUrl); 

9. Skonfiguruj limit czasu

Możemy skonfigurować RestTemplate do przekroczenia limitu czasu, po prostu używając ClientHttpRequestFactory :

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory()); private ClientHttpRequestFactory getClientHttpRequestFactory() { int timeout = 5000; HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setConnectTimeout(timeout); return clientHttpRequestFactory; }

I możemy użyć HttpClient do dalszych opcji konfiguracji:

private ClientHttpRequestFactory getClientHttpRequestFactory() { int timeout = 5000; RequestConfig config = RequestConfig.custom() .setConnectTimeout(timeout) .setConnectionRequestTimeout(timeout) .setSocketTimeout(timeout) .build(); CloseableHttpClient client = HttpClientBuilder .create() .setDefaultRequestConfig(config) .build(); return new HttpComponentsClientHttpRequestFactory(client); }

10. Wniosek

W tym artykule omówiliśmy główne zlecenia HTTP, używając RestTemplate do organizowania żądań przy użyciu tych wszystkich.

Jeśli chcesz dowiedzieć się, jak przeprowadzić uwierzytelnianie za pomocą szablonu, zapoznaj się z naszym artykułem na temat uwierzytelniania podstawowego za pomocą RestTemplate.

Implementację wszystkich tych przykładów i fragmentów kodu można znaleźć na GitHub.