Articles

La Guía del RestTemplate

Posted on

Presentación

En este tutorial, vamos a ilustrar el amplio rango de operaciones en las que se puede utilizar, y utilizar bien, el cliente REST de Spring: RestTemplate.

Para la parte de la API de todos los ejemplos, ejecutaremos el servicio RESTful desde aquí.

Más lecturas:

Autenticación básica con el RestTemplate

Cómo hacer autenticación básica con el Spring RestTemplate.
Leer más →

RestTemplate con autenticación Digest

Cómo configurar la autenticación Digest para el RestTemplate de Spring usando HttpClient 4.
Leer más →

Explorando el TestRestTemplate de Spring Boot

Aprende a utilizar el nuevo TestRestTemplate de Spring Boot para probar una API sencilla.
Lee más →

Aviso de descatalogación

A partir de Spring Framework 5, junto a la pila WebFlux, Spring introdujo un nuevo cliente HTTP llamado WebClient.

WebClient es un cliente HTTP moderno y alternativo a RestTemplate. No sólo proporciona una API síncrona tradicional, sino que también soporta un enfoque eficiente no bloqueante y asíncrono.

Dicho esto, si estamos desarrollando nuevas aplicaciones o migrando una antigua, es una buena idea utilizar WebClient. De cara al futuro, RestTemplate quedará obsoleto en futuras versiones.

Usa GET para recuperar recursos

3.1. Obtener JSON plano

Empecemos de forma sencilla y hablemos de las peticiones GET, con un ejemplo rápido usando la API getForEntity():

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

Nota que tenemos acceso completo a la respuesta HTTP, por lo que podemos hacer cosas como comprobar el código de estado para asegurarnos de que la operación ha sido exitosa o trabajar con el cuerpo real de la respuesta:

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

Aquí estamos trabajando con el cuerpo de la respuesta como un String estándar y utilizando Jackson (y la estructura de nodos JSON que proporciona Jackson) para verificar algunos detalles.

3.2. Recuperar POJO en lugar de JSON

También podemos mapear la respuesta directamente a un DTO de recursos:

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

Ahora podemos simplemente utilizar la API getForObject en la plantilla:

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

Utilizar HEAD para recuperar cabeceras

Ahora vamos a echar un vistazo rápido al uso de HEAD antes de pasar a los métodos más comunes.

Aquí vamos a utilizar la API headForHeaders():

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

Utilizar POST para crear un recurso

Para crear un nuevo recurso en la API, podemos hacer un buen uso de las APIs postForLocation(), postForObject() o postForEntity().

La primera devuelve el URI del Recurso recién creado, mientras que la segunda devuelve el propio Recurso.

5.1. La API postForObject()

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. La API postForLocation()

De igual forma, veamos la operación que en lugar de devolver el Recurso completo, sólo devuelve la Ubicación de ese Recurso recién creado:

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

5.3. La API exchange()

Veamos cómo hacer un POST con la API exchange más 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. Enviar los datos del formulario

A continuación, vamos a ver cómo enviar un formulario utilizando el método POST.

En primer lugar, tenemos que establecer el encabezado Content-Type a application/x-www-form-urlencoded.

Esto asegura que una gran cadena de consulta puede ser enviada al servidor, conteniendo pares nombre/valor separados por &:

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

Podemos envolver las variables del formulario en un LinkedMultiValueMap:

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

A continuación, construimos la Request utilizando una instancia HttpEntity:

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

Por último, podemos conectarnos al servicio REST llamando a restTemplate.postForEntity() en el Endpoint: /foos/form

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

Utilizar OPTIONS para obtener las operaciones permitidas

A continuación, vamos a echar un vistazo rápido al uso de una petición OPTIONS y a explorar las operaciones permitidas en un URI específico utilizando este tipo de petición; la API es optionsForAllow:

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 un recurso

A continuación, empezaremos a ver PUT y más concretamente la API exchange() para esta operación, ya que la plantilla.put es bastante sencilla.

7.1. PUT simple con exchange()

Comenzaremos con una operación PUT simple contra la API – y ten en cuenta que la operación no está devolviendo un cuerpo al 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 con exchange() y un callback de petición

A continuación, vamos a utilizar un callback de petición para emitir un PUT.

Asegurémonos de preparar la devolución de llamada, donde podemos establecer todas las cabeceras que necesitamos así como un cuerpo de petición:

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

A continuación, creamos el Recurso con una petición POST:

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

Y luego actualizamos el 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 eliminar un Recurso

Para eliminar un Recurso existente, haremos un uso rápido de la API delete():

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

Configurar el tiempo de espera

Podemos configurar RestTemplate para que se agote el tiempo de espera simplemente usando ClientHttpRequestFactory:

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

Y podemos usar HttpClient para más opciones de configuración:

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

Conclusión

En este artículo, hemos repasado los principales Verbos HTTP, utilizando RestTemplate para orquestar peticiones utilizando todos ellos.

Si quieres profundizar en cómo hacer la autenticación con la plantilla, echa un vistazo a nuestro artículo sobre Basic Auth con RestTemplate.

La implementación de todos estos ejemplos y fragmentos de código se puede encontrar en GitHub.

Inicia con Spring 5 y Spring Boot 2, a través del curso Learn Spring: >> CONSULTA EL CURSO
.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *