La guida a RestTemplate

1. Panoramica

In questo tutorial, illustreremo l'ampia gamma di operazioni in cui il client Spring REST - RestTemplate - può essere utilizzato e utilizzato bene.

Per il lato API di tutti gli esempi, eseguiremo il servizio RESTful da qui.

2. Avviso di ritiro

A partire da Spring Framework 5, insieme allo stack WebFlux, Spring ha introdotto un nuovo client HTTP chiamato WebClient .

WebClient è un client HTTP moderno e alternativo a RestTemplate . Non solo fornisce un'API sincrona tradizionale, ma supporta anche un approccio efficiente non bloccante e asincrono.

Detto questo, se stiamo sviluppando nuove applicazioni o migrando una vecchia, è una buona idea usare WebClient . In futuro, RestTemplate sarà deprecato nelle versioni future.

3. Utilizzare GET per recuperare le risorse

3.1. Ottieni Plain JSON

Cominciamo in modo semplice e parliamo delle richieste GET, con un rapido esempio utilizzando l' 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));

Si noti che abbiamo pieno accesso alla risposta HTTP , quindi possiamo fare cose come controllare il codice di stato per assicurarci che l'operazione sia andata a buon fine o lavorare con il corpo effettivo della risposta:

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

Stiamo lavorando con il corpo della risposta come una stringa standard qui e utilizzando Jackson (e la struttura del nodo JSON fornita da Jackson) per verificare alcuni dettagli.

3.2. Recupero POJO invece di JSON

Possiamo anche mappare la risposta direttamente a un DTO risorsa:

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

Ora possiamo semplicemente utilizzare l' API getForObject nel modello:

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

4. Utilizzare HEAD per recuperare le intestazioni

Diamo ora una rapida occhiata all'uso di HEAD prima di passare ai metodi più comuni.

Useremo l' API headForHeaders () qui:

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

5. Utilizzare POST per creare una risorsa

Per creare una nuova risorsa nell'API, possiamo fare buon uso delle API postForLocation () , postForObject () o postForEntity () .

Il primo restituisce l'URI della Risorsa appena creata, mentre il secondo restituisce la Risorsa stessa.

5.1. L' 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. L' API postForLocation ()

Allo stesso modo, diamo un'occhiata all'operazione che invece di restituire l'intera Risorsa, restituisce semplicemente la Posizione di quella Risorsa appena creata:

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

5.3. L' API exchange ()

Diamo un'occhiata a come eseguire un POST con l' API di scambio più generica :

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. Invia i dati del modulo

Successivamente, diamo un'occhiata a come inviare un modulo utilizzando il metodo POST.

Per prima cosa, dobbiamo impostare l' intestazione Content-Type su application / x-www-form-urlencoded.

Ciò garantisce che una stringa di query di grandi dimensioni possa essere inviata al server, contenente coppie nome / valore separate da & :

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

We can wrap the form variables into a LinkedMultiValueMap:

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

Next, we build the Request using an HttpEntity instance:

HttpEntity
    
      request = new HttpEntity(map, headers);
    

Finally, we can connect to the REST service by calling restTemplate.postForEntity() on the Endpoint: /foos/form

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

6. Use OPTIONS to Get Allowed Operations

Next, we're going to have a quick look at using an OPTIONS request and exploring the allowed operations on a specific URI using this kind of request; the API is optionsForAllow:

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

7. Use PUT to Update a Resource

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

Per rimuovere una risorsa esistente, utilizzeremo rapidamente l' API delete () :

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

9. Configurare il timeout

Possiamo configurare RestTemplate per il timeout semplicemente usando ClientHttpRequestFactory :

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

E possiamo usare HttpClient per ulteriori opzioni di configurazione:

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. Conclusione

In questo articolo, abbiamo esaminato i principali verbi HTTP, utilizzando RestTemplate per orchestrare le richieste utilizzando tutti questi.

Se vuoi approfondire come eseguire l'autenticazione con il modello, consulta il nostro articolo sull'autenticazione di base con RestTemplate.

L'implementazione di tutti questi esempi e frammenti di codice può essere trovata su GitHub.