Articles

The Guide to RestTemplate

Posted on

Overview

Neste tutorial, vamos ilustrar a vasta gama de operações onde o Cliente Spring REST – RestTemplate – pode ser utilizado, e bem utilizado.

Para o lado API de todos os exemplos, vamos executar o serviço RESTful a partir daqui.

Outra leitura:

Autenticação Básica com o RestTemplate de Primavera

Como fazer a Autenticação Básica com o RestTemplate de Primavera.
Leia mais →

RestTemplate with Digest Authentication

Como configurar a Autenticação Digest para o Spring RestTemplate utilizando o HttpClient 4.
Ler mais →

Explorar o Spring Boot TestRestTemplate

Saiba como utilizar o novo TestRestTemplate na Spring Boot para testar um API simples.
Ler mais →

Notificação de Depreciação

As of Spring Framework 5, juntamente com a pilha WebFlux, Spring introduziu um novo cliente HTTP chamado WebClient.

WebClient é um cliente HTTP moderno e alternativo ao RestTemplate. Não só fornece uma API tradicional síncrona, como também suporta uma abordagem eficiente de não bloqueio e assíncrona.

P>Dito isto, se estamos a desenvolver novas aplicações ou a migrar uma antiga, é uma boa ideia utilizar o Cliente Web. Avançando, RestTemplate será depreciado em versões futuras.

Utilizar GET para Recuperar Recursos

h3>3.1. Get Plain JSON

Let’s start simple and talk about GET requests, with a quick example using the getForEntity() API:

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

Notificação de que temos acesso total à resposta HTTP, para que possamos fazer coisas como verificar o código de estado para garantir que a operação foi bem sucedida ou trabalhar com o corpo real da resposta:

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

Estamos a trabalhar com o corpo da resposta como uma String padrão e a utilizar Jackson (e a estrutura do nó JSON que Jackson fornece) para verificar alguns detalhes.

3.2. Recuperando POJO em vez de JSON

Podemos também mapear a resposta directamente a um recurso DTO:

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

Agora podemos simplesmente usar o getForObject API no modelo:

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

Utilizar HEAD para Recuperar Cabeçalhos

Vejamos agora a utilização de HEAD antes de passarmos aos métodos mais comuns.

Vamos utilizar a API headForHeaders() aqui:

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

Utilizar POST para Criar um Recurso

A fim de criar um novo Recurso na API, podemos fazer bom uso das APIs postForLocation(), postForObject() ou postForEntity().

A primeira devolve o URI do novo Recurso criado, enquanto a segunda devolve o próprio Recurso.

5.1. O postForObject() API

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

5.2. O postForLocation() API

Simplesmente, vamos dar uma vista de olhos à operação que, em vez de devolver o Recurso completo, apenas devolve a Localização daquele Recurso recentemente criado:

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

5.3. A troca() API

Vejamos como fazer um POST com a API de troca mais genérica:

RestTemplate restTemplate = new RestTemplate();HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));ResponseEntity<Foo> 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. Submeter dados do formulário

Next, vamos ver como submeter um formulário usando o método POST.

P>Primeiro, precisamos de definir o cabeçalho Content-Type para aplicação/x-www-form-urlencoded.

Esta acção assegura que uma grande cadeia de consulta pode ser enviada para o servidor, contendo pares nome/valor separados por &:

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

Podemos envolver as variáveis do formulário num LinkedMultiValueMap:

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

Next, construímos o Pedido utilizando uma instância HttpEntity:

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

Finalmente, podemos ligar ao serviço REST chamando o RestTemplate.postForEntity() no Endpoint: /foos/form

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

Utilizar OPÇÕES para obter operações permitidas

P>Próximo, vamos dar uma vista de olhos rápida ao utilizar um pedido de OPÇÕES e explorar as operações permitidas num URI específico utilizando este tipo de pedido; a API é opçõesForAllow:

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

Utilizar PUT para Actualizar um Recurso

P>Próximo, vamos começar a analisar o PUT e mais especificamente a troca() API para esta operação, desde o modelo.colocar API é bastante simples.

7.1. PUT simples Com troca()

Começaremos com uma simples operação PUT contra o API – e tenhamos em mente que a operação não está a devolver um corpo ao cliente:

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

7.2. PUT Com troca() e um Request Callback

Next, vamos utilizar um Request Callback para emitir um PUT.

Vamo-nos certificar de que preparamos o retorno de chamada, onde podemos definir todos os cabeçalhos de que precisamos, bem como um corpo de pedido:

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()); };}

P>Próximo, criamos o Recurso com um pedido de retorno de chamada:

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

E depois actualizamos o Recurso:

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);

Utilizar DELETE para Remover um Recurso

Para remover um Recurso existente, faremos rápido uso da API delete():

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

Configure Timeout

Podemos configurar o RestTemplate para o time out simplesmente usando ClientHttpRequestFactory:

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

E podemos usar o HttpClient para outras opções de configuração:

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);}

Conclusion

Neste artigo, revimos os principais Verbos HTTP, usando RestTemplate para orquestrar pedidos usando todos estes.

Se quiseres pesquisar como fazer autenticação com o modelo, consulta o nosso artigo sobre Auth Básico com RestTemplate.

A implementação de todos estes exemplos e trechos de código pode ser encontrada no GitHub.

Comece com Spring 5 e Spring Boot 2, através do curso Learn Spring:

>> VERIFIQUE O CURSO

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *