Spring Boot

SpringBoot

Tutorial SpringBoot: Clientes RestTemplate y RestClient

Aprende a usar RestTemplate y RestClient y sus diferencias en Spring Boot para realizar peticiones http a API REST externas y consumir datos desde backend.

Aprende SpringBoot GRATIS y certifícate

Qué son y qué diferencias hay entre RestTemplate y RestClient

En el desarrollo de aplicaciones con Spring Boot, es común necesitar consumir servicios externos mediante peticiones HTTP a APIs REST. Para facilitar esta tarea, Spring ofrece herramientas como RestTemplate y RestClient, que actúan como clientes HTTP dentro de nuestras aplicaciones.

RestTemplate ha sido durante mucho tiempo la clase estándar para realizar peticiones HTTP de forma síncrona en aplicaciones Spring. Permite ejecutar operaciones HTTP como GET, POST, PUT y DELETE de manera sencilla. Un ejemplo de su uso sería:

RestTemplate restTemplate = new RestTemplate();
String respuesta = restTemplate.getForObject("https://api.ejemplo.com/datos", String.class);

Por otro lado, RestClient es la solución más moderna que proporciona Spring para interactuar con servicios REST. Introducido en versiones recientes, RestClient ofrece una API fluida y más flexible que se adapta mejor a las necesidades actuales del desarrollo en Java. Un ejemplo de uso es:

RestClient restClient = RestClient.create();
String respuesta = restClient.get()
    .uri("https://api.ejemplo.com/datos")
    .retrieve()
    .body(String.class);

Una diferencia clave entre ambas herramientas es el enfoque en su diseño. RestTemplate sigue un estilo imperativo clásico, mientras que RestClient adopta un estilo más funcional y fluido. Esto permite que RestClient se integre de manera más natural con las características modernas de Java y facilite la construcción de peticiones más complejas de forma concisa.

Además, RestClient ofrece una mejor extensibilidad y personalización. Permite configurar aspectos avanzados como cabeceras personalizadas, autenticación, serialización y deserialización de datos, y manejo detallado de errores. Esto se logra mediante una API que encadena métodos y mejora la legibilidad del código.

En términos de rendimiento, RestClient está diseñado para trabajar de manera eficiente con las funcionalidades reactivas de Spring, como WebFlux. Aunque RestTemplate puede usarse en entornos reactivos, no está optimizado para ello, lo que puede resultar en un rendimiento subóptimo en aplicaciones que requieren alta concurrencia y escalabilidad.

Otra diferencia importante es el soporte y la evolución futura. RestTemplate está en vías de ser reemplazado y puede que no reciba nuevas actualizaciones importantes. RestClient, al ser la solución más reciente, cuenta con el respaldo activo de la comunidad de Spring y se espera que se siga desarrollando y mejorando en versiones futuras.

Es relevante mencionar que RestClient facilita el manejo de entidades de forma genérica y permite una mayor flexibilidad en la gestión de tipos de respuesta, lo que simplifica el trabajo con diferentes formatos de datos y servicios externos que puedan tener comportamientos variados.

Aunque ambos permiten realizar peticiones HTTP en aplicaciones Spring, RestClient ofrece una serie de ventajas y mejoras significativas respecto a RestTemplate. La adopción de RestClient en nuevos proyectos es recomendable para aprovechar las mejoras en diseño, eficiencia y soporte a largo plazo que ofrece esta herramienta.

Uso de RestTemplate para peticiones HTTP de API REST externas

Para utilizar RestTemplate en un proyecto Spring Boot 3, es necesario declararlo como un componente gestionado por el contenedor de Spring. Esto se logra mediante la configuración de un bean en una clase de configuración:

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Una vez configurado, se puede inyectar el RestTemplate en cualquier componente de la aplicación utilizando la anotación @Autowired:

@Service
public class ApiService {

    private final RestTemplate restTemplate;

    public ApiService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    // Métodos que utilizan restTemplate
}

Para realizar una petición GET y obtener un recurso desde una API externa, se puede utilizar el método getForObject o getForEntity de RestTemplate. Por ejemplo:

String url = "https://api.ejemplo.com/usuarios/1";
Usuario usuario = restTemplate.getForObject(url, Usuario.class);

En este ejemplo, se está obteniendo un objeto Usuario desde la URL especificada. Es importante que la clase Usuario esté correctamente mapeada a la estructura de datos que devuelve la API externa.

Para enviar datos a través de una petición POST, se utiliza el método postForObject:

String url = "https://api.ejemplo.com/usuarios";
Usuario nuevoUsuario = new Usuario("Juan", "Pérez", "juan.perez@example.com");
Usuario resultado = restTemplate.postForObject(url, nuevoUsuario, Usuario.class);

Aquí, se envía un objeto Usuario a la API externa para crear un nuevo recurso. El resultado es el objeto creado, que puede incluir información adicional proporcionada por el servidor.

Si es necesario establecer cabeceras HTTP personalizadas, como autenticación o tipo de contenido, se pueden utilizar las clases HttpHeaders y HttpEntity:

String url = "https://api.ejemplo.com/usuarios";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth("token_de_acceso");

Usuario nuevoUsuario = new Usuario("María", "López", "maria.lopez@example.com");
HttpEntity<Usuario> request = new HttpEntity<>(nuevoUsuario, headers);

ResponseEntity<Usuario> response = restTemplate.postForEntity(url, request, Usuario.class);

En este caso, se está enviando una petición POST con cabeceras personalizadas, incluyendo un token de autenticación Bearer.

Para manejar peticiones PUT y actualizar recursos existentes, se utiliza el método put:

String url = "https://api.ejemplo.com/usuarios/1";
Usuario usuarioActualizado = new Usuario("Juan", "Pérez González", "juan.perez@example.com");
restTemplate.put(url, usuarioActualizado);

La eliminación de recursos mediante una petición DELETE se realiza con el método delete:

String url = "https://api.ejemplo.com/usuarios/1";
restTemplate.delete(url);

Es común que las APIs externas requieran parámetros en las URLs o en el cuerpo de la petición. RestTemplate permite pasar parámetros de forma sencilla usando templates y mapas de valores:

String url = "https://api.ejemplo.com/usuarios/{id}";
Map<String, String> params = new HashMap<>();
params.put("id", "1");

Usuario usuario = restTemplate.getForObject(url, Usuario.class, params);

Además, RestTemplate soporta el uso de interceptores para manipular las peticiones y respuestas. Esto es útil para implementar funcionalidades transversales como el logueo o la modificación dinámica de cabeceras:

restTemplate.getInterceptors().add((request, body, execution) -> {
    request.getHeaders().add("X-Custom-Header", "ValorPersonalizado");
    return execution.execute(request, body);
});

Para manejar errores y excepciones durante las peticiones, se puede utilizar un ResponseErrorHandler personalizado:

restTemplate.setErrorHandler(new ResponseErrorHandler() {
    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return response.getStatusCode().isError();
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // Lógica de manejo de errores
    }
});

Si se requiere configurar aspectos más avanzados, como el manejo de timeout o la gestión de conexiones, es posible personalizar el ClientHttpRequestFactory:

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(Duration.ofSeconds(10));
factory.setReadTimeout(Duration.ofSeconds(30));

RestTemplate restTemplate = new RestTemplate(factory);

En este ejemplo, se establecen tiempos de espera para la conexión y la lectura de datos, lo cual es esencial para aplicaciones que interactúan con servicios externos y necesitan garantizar una resiliencia adecuada.

Para finalizar, es importante recordar que RestTemplate trabaja de forma síncrona y bloqueante. Si la aplicación requiere un manejo asíncrono o reactivo, se debe considerar el uso de otras alternativas como WebClient.

Utilizar RestTemplate correctamente permite que las aplicaciones Spring Boot 3 consuman servicios externos de manera eficiente, manteniendo un código limpio y fácil de mantener. La flexibilidad que ofrece en la configuración y personalización facilita su adaptación a diferentes escenarios y requisitos específicos de las APIs con las que se interactúa.

Uso de RestClient para peticiones HTTP de API REST externas

El RestClient es una herramienta moderna proporcionada por Spring Framework para facilitar la realización de peticiones HTTP a APIs REST externas. Con una API más fluida y flexible que su predecesor RestTemplate, RestClient permite construir y ejecutar peticiones de manera concisa y eficiente.

Para utilizar RestClient en un proyecto de Spring Boot 3, es necesario configurar un bean que lo provea. A diferencia de RestTemplate, la instancia de RestClient se crea mediante un builder, lo que permite una configuración más granular:

@Configuration
public class RestClientConfig {

    @Bean
    public RestClient restClient() {
        return RestClient.builder()
                .baseUri("https://api.ejemplo.com")
                .build();
    }
}

En este ejemplo, se establece una URI base para todas las peticiones, facilitando la construcción de URLs relativas en las operaciones posteriores.

Una vez configurado, se puede inyectar el RestClient en los componentes necesarios utilizando la anotación @Autowired o por inyección de constructor:

@Service
public class ApiService {

    private final RestClient restClient;

    public ApiService(RestClient restClient) {
        this.restClient = restClient;
    }

    // Métodos que utilizan restClient
}

Para realizar una petición GET y obtener un recurso desde una API externa, se utiliza el método get() del RestClient, seguido de la especificación del URI y el tipo de respuesta esperado:

public Usuario obtenerUsuario(Long id) {
    return restClient.get()
            .uri("/usuarios/{id}", id)
            .retrieve()
            .body(Usuario.class);
}

En este caso, se está solicitando el usuario con el identificador proporcionado, y el resultado se mapea directamente a un objeto Usuario.

Para enviar datos mediante una petición POST, el RestClient permite construir la petición especificando el cuerpo y el tipo de respuesta:

public Usuario crearUsuario(Usuario nuevoUsuario) {
    return restClient.post()
            .uri("/usuarios")
            .body(nuevoUsuario)
            .retrieve()
            .body(Usuario.class);
}

Aquí, se está creando un nuevo usuario enviando los datos en el cuerpo de la petición y esperando como respuesta el usuario creado.

Si es necesario actualizar un recurso existente mediante una petición PUT, se utiliza el método put() de manera similar:

public void actualizarUsuario(Long id, Usuario usuarioActualizado) {
    restClient.put()
            .uri("/usuarios/{id}", id)
            .body(usuarioActualizado)
            .retrieve()
            .toBodilessEntity();
}

En este ejemplo, se envía el objeto usuarioActualizado al endpoint correspondiente, sin esperar un cuerpo en la respuesta.

Para eliminar un recurso con una petición DELETE, se utiliza el método delete():

public void eliminarUsuario(Long id) {
    restClient.delete()
            .uri("/usuarios/{id}", id)
            .retrieve()
            .toBodilessEntity();
}

El RestClient permite configurar cabeceras HTTP y parámetros de consulta de manera sencilla. Por ejemplo, para agregar una cabecera de autenticación:

public List<Usuario> listarUsuarios(String token) {
    return restClient.get()
            .uri("/usuarios")
            .header("Authorization", "Bearer " + token)
            .retrieve()
            .body(new ParameterizedTypeReference<List<Usuario>>() {});
}

En este caso, se está añadiendo una cabecera Authorization con un token Bearer, y se espera una lista de usuarios como respuesta.

Cuando se requiere enviar parámetros en la URL o en los parámetros de consulta, el RestClient permite especificarlos directamente en el método uri():

public List<Usuario> buscarUsuarios(String nombre, String email) {
    return restClient.get()
            .uri(uriBuilder -> uriBuilder
                .path("/usuarios/buscar")
                .queryParam("nombre", nombre)
                .queryParam("email", email)
                .build())
            .retrieve()
            .body(new ParameterizedTypeReference<List<Usuario>>() {});
}

Este ejemplo muestra cómo construir una URI con parámetros de consulta dinámicos utilizando un UriBuilder.

El manejo de respuestas y su conversión a objetos Java es flexible en RestClient. Si se requiere acceder directamente al ResponseEntity para obtener detalles como el código de estado o las cabeceras, se puede utilizar:

public ResponseEntity<Usuario> obtenerUsuarioConDetalles(Long id) {
    return restClient.get()
            .uri("/usuarios/{id}", id)
            .retrieve()
            .toEntity(Usuario.class);
}

Para configurar timeout o establecer otras propiedades del cliente HTTP subyacente, se puede personalizar el HttpClient utilizado por RestClient:

@Bean
public RestClient restClient() {
    HttpClient httpClient = HttpClient.create()
            .responseTimeout(Duration.ofSeconds(5));
    ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);

    return RestClient.builder()
            .connector(connector)
            .build();
}

En esta configuración, se establece un timeout de 5 segundos para las respuestas, lo que es importante para mantener la resiliencia de la aplicación ante servicios externos lentos o no disponibles.

El RestClient también soporta la adición de interceptores o filters para modificar peticiones y respuestas de forma centralizada:

@Bean
public RestClient restClient() {
    ExchangeFilterFunction logFilter = ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
        System.out.println("Realizando petición a " + clientRequest.url());
        return Mono.just(clientRequest);
    });

    return RestClient.builder()
            .filter(logFilter)
            .build();
}

Este filter de ejemplo permite registrar en el log cada petición realizada, mejorando la observabilidad de las interacciones con APIs externas.

El manejo de errores en RestClient se puede realizar utilizando el método onStatus() para comprobar códigos de estado y lanzar excepciones personalizadas:

public Usuario obtenerUsuario(Long id) {
    return restClient.get()
            .uri("/usuarios/{id}", id)
            .retrieve()
            .onStatus(HttpStatus::is4xxClientError, response -> {
                return Mono.error(new ClienteException("Error del cliente"));
            })
            .onStatus(HttpStatus::is5xxServerError, response -> {
                return Mono.error(new ServidorException("Error del servidor"));
            })
            .body(Usuario.class);
}

Con este enfoque, se puede proporcionar un manejo específico para diferentes tipos de errores HTTP, mejorando la robustez de la aplicación.

Para casos en los que se necesite enviar solicitudes con tipos de contenido específicos, como JSON o XML, el RestClient utiliza los encoders y decoders configurados en el contexto de Spring Web. Si se requiere personalización, se pueden especificar encoders adicionales:

@Bean
public RestClient restClient() {
    return RestClient.builder()
            .exchangeStrategies(ExchangeStrategies.builder()
                .codecs(configurer -> configurer
                    .defaultCodecs()
                    .jackson2JsonEncoder(new Jackson2JsonEncoder(new ObjectMapper(), MediaType.APPLICATION_JSON)))
                .build())
            .build();
}

Esta configuración permite ajustar cómo se serializan y deserializan los objetos en las peticiones y respuestas, asegurando la compatibilidad con los servicios externos.

En términos de asincronía, aunque RestClient está diseñado principalmente para operaciones síncronas, puede integrarse con APIs reactivas cuando se utiliza en combinación con WebClient, permitiendo un manejo más eficiente de los recursos en aplicaciones de alta concurrencia.

Es importante destacar que, al utilizar RestClient, se adopta una forma de construir peticiones más alineada con las prácticas modernas de Java, utilizando un estilo fluido y enfocado en la inmutabilidad y la composición de funciones.

Aprende SpringBoot GRATIS online

Ejercicios de esta lección Clientes RestTemplate y RestClient

Evalúa tus conocimientos de esta lección Clientes RestTemplate y RestClient con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

API Query By Example (QBE)

Spring Boot
Test

Identificadores y relaciones JPA

Spring Boot
Puzzle

Borrar datos de base de datos

Spring Boot
Test

Web y Test Starters

Spring Boot
Puzzle

Métodos find en repositorios

Spring Boot
Test

Controladores Spring MVC

Spring Boot
Código

Inserción de datos

Spring Boot
Test

CRUD Customers Spring MVC + Spring Data JPA

Spring Boot
Proyecto

Backend API REST con Spring Boot

Spring Boot
Proyecto

Controladores Spring REST

Spring Boot
Código

Uso de Spring con Thymeleaf

Spring Boot
Puzzle

API Specification

Spring Boot
Puzzle

Registro de usuarios

Spring Boot
Test

Crear entidades JPA

Spring Boot
Código

Asociaciones en JPA

Spring Boot
Test

Asociaciones de entidades JPA

Spring Boot
Código

Integración con Vue

Spring Boot
Test

Consultas JPQL

Spring Boot
Código

Open API y cómo agregarlo en Spring Boot

Spring Boot
Puzzle

Uso de Controladores REST

Spring Boot
Puzzle

Repositorios reactivos

Spring Boot
Test

Inyección de dependencias

Spring Boot
Test

Introducción a Spring Boot

Spring Boot
Test

CRUD y JPA Repository

Spring Boot
Puzzle

Inyección de dependencias

Spring Boot
Código

Vista en Spring MVC con Thymeleaf

Spring Boot
Test

Servicios en Spring

Spring Boot
Código

Operadores Reactivos

Spring Boot
Puzzle

Configuración de Vue

Spring Boot
Puzzle

Entidades JPA

Spring Boot
Test

Integración con Angular

Spring Boot
Test

API Specification

Spring Boot
Test

API Query By Example (QBE)

Spring Boot
Puzzle

Controladores MVC

Spring Boot
Test

Anotaciones y mapeo en JPA

Spring Boot
Puzzle

Consultas JPQL con @Query en Spring Data JPA

Spring Boot
Test

Repositorios Spring Data

Spring Boot
Test

Inyección de dependencias

Spring Boot
Puzzle

Data JPA y Mail Starters

Spring Boot
Test

Configuración de Angular

Spring Boot
Puzzle

Controladores Spring REST

Spring Boot
Test

Configuración de Controladores MVC

Spring Boot
Puzzle

Consultas JPQL con @Query en Spring Data JPA

Spring Boot
Puzzle

Actualizar datos de base de datos

Spring Boot
Test

Verificar token JWT en peticiones

Spring Boot
Test

Login de usuarios

Spring Boot
Test

Integración con React

Spring Boot
Test

Configuración de React

Spring Boot
Puzzle

Todas las lecciones de SpringBoot

Accede a todas las lecciones de SpringBoot y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Spring Boot

Spring Boot

Introducción Y Entorno

Spring Boot Starters

Spring Boot

Introducción Y Entorno

Inyección De Dependencias

Spring Boot

Introducción Y Entorno

Controladores Spring Mvc

Spring Boot

Spring Web

Vista En Spring Mvc Con Thymeleaf

Spring Boot

Spring Web

Controladores Spring Rest

Spring Boot

Spring Web

Open Api Y Cómo Agregarlo En Spring Boot

Spring Boot

Spring Web

Servicios En Spring

Spring Boot

Spring Web

Clientes Resttemplate Y Restclient

Spring Boot

Spring Web

Rxjava En Spring Web

Spring Boot

Spring Web

Crear Entidades Jpa

Spring Boot

Persistencia Spring Data

Asociaciones De Entidades Jpa

Spring Boot

Persistencia Spring Data

Repositorios Spring Data

Spring Boot

Persistencia Spring Data

Métodos Find En Repositorios

Spring Boot

Persistencia Spring Data

Inserción De Datos

Spring Boot

Persistencia Spring Data

Actualizar Datos De Base De Datos

Spring Boot

Persistencia Spring Data

Borrar Datos De Base De Datos

Spring Boot

Persistencia Spring Data

Consultas Jpql Con @Query En Spring Data Jpa

Spring Boot

Persistencia Spring Data

Api Query By Example (Qbe)

Spring Boot

Persistencia Spring Data

Api Specification

Spring Boot

Persistencia Spring Data

Repositorios Reactivos

Spring Boot

Persistencia Spring Data

Introducción E Instalación De Apache Kafka

Spring Boot

Mensajería Asíncrona

Crear Proyecto Con Apache Kafka

Spring Boot

Mensajería Asíncrona

Creación De Producers

Spring Boot

Mensajería Asíncrona

Creación De Consumers

Spring Boot

Mensajería Asíncrona

Kafka Streams En Spring Boot

Spring Boot

Mensajería Asíncrona

Introducción A Spring Webflux

Spring Boot

Reactividad Webflux

Spring Data R2dbc

Spring Boot

Reactividad Webflux

Controlador Rest Reactivo Basado En Anotaciones

Spring Boot

Reactividad Webflux

Controlador Rest Reactivo Funcional

Spring Boot

Reactividad Webflux

Operadores Reactivos Básicos

Spring Boot

Reactividad Webflux

Operadores Reactivos Avanzados

Spring Boot

Reactividad Webflux

Cliente Reactivo Webclient

Spring Boot

Reactividad Webflux

Introducción A Spring Security

Spring Boot

Seguridad Con Spring Security

Seguridad Basada En Formulario En Mvc Con Thymeleaf

Spring Boot

Seguridad Con Spring Security

Registro De Usuarios

Spring Boot

Seguridad Con Spring Security

Login De Usuarios

Spring Boot

Seguridad Con Spring Security

Verificar Token Jwt En Peticiones

Spring Boot

Seguridad Con Spring Security

Seguridad Jwt En Api Rest Spring Web

Spring Boot

Seguridad Con Spring Security

Seguridad Jwt En Api Rest Reactiva Spring Webflux

Spring Boot

Seguridad Con Spring Security

Autenticación Y Autorización Con Anotaciones

Spring Boot

Seguridad Con Spring Security

Testing Unitario De Componentes Y Servicios

Spring Boot

Testing Con Spring Test

Testing De Repositorios Spring Data Jpa

Spring Boot

Testing Con Spring Test

Testing Controladores Spring Mvc Con Thymeleaf

Spring Boot

Testing Con Spring Test

Testing Controladores Rest Con Json

Spring Boot

Testing Con Spring Test

Testing De Aplicaciones Reactivas Webflux

Spring Boot

Testing Con Spring Test

Testing De Seguridad Spring Security

Spring Boot

Testing Con Spring Test

Testing Con Apache Kafka

Spring Boot

Testing Con Spring Test

Integración Con Angular

Spring Boot

Integración Frontend

Integración Con React

Spring Boot

Integración Frontend

Integración Con Vue

Spring Boot

Integración Frontend

Accede GRATIS a SpringBoot y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Aprender a usar RestTemplate
  • Aprender a usar RestClient
  • Entender las diferencias entre RestTemplate y RestClient