SpringBoot
Tutorial SpringBoot: Gestión de errores RestControllerAdvice
Aprende a manejar errores centralizados en APIs REST con @RestControllerAdvice y @ExceptionHandler en Spring Boot para mejorar tu código.
Aprende SpringBoot y certifícate@ExceptionHandler y @RestControllerAdvice
La gestión centralizada de errores en Spring Boot permite manejar excepciones de forma consistente en toda la aplicación REST. En lugar de duplicar código de manejo de errores en cada controlador, Spring proporciona un mecanismo elegante para centralizar esta responsabilidad mediante anotaciones específicas.
Fundamentos de @ExceptionHandler
La anotación @ExceptionHandler permite definir métodos que capturan y procesan excepciones específicas dentro de un controlador. Este enfoque básico funciona bien cuando necesitas manejar errores particulares de un solo controlador.
@RestController
@RequestMapping("/api/usuarios")
public class UsuarioController {
@Autowired
private UsuarioService usuarioService;
@GetMapping("/{id}")
public Usuario obtenerUsuario(@PathVariable Long id) {
return usuarioService.buscarPorId(id);
}
// Manejo local de excepciones
@ExceptionHandler(UsuarioNoEncontradoException.class)
public ResponseEntity<String> manejarUsuarioNoEncontrado(UsuarioNoEncontradoException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body("Usuario no encontrado: " + ex.getMessage());
}
}
El método anotado con @ExceptionHandler intercepta automáticamente las excepciones del tipo especificado que ocurran en cualquier método del mismo controlador. Sin embargo, este enfoque tiene limitaciones cuando necesitas aplicar el mismo manejo de errores en múltiples controladores.
Introducción a @RestControllerAdvice
La anotación @RestControllerAdvice extiende las capacidades de manejo de errores a nivel global de la aplicación. Esta anotación combina @ControllerAdvice
con @ResponseBody
, lo que la hace ideal para APIs REST que devuelven respuestas JSON.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UsuarioNoEncontradoException.class)
public ResponseEntity<ErrorResponse> manejarUsuarioNoEncontrado(UsuarioNoEncontradoException ex) {
ErrorResponse error = new ErrorResponse(
"USUARIO_NO_ENCONTRADO",
ex.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(ValidationException.class)
public ResponseEntity<ErrorResponse> manejarValidacion(ValidationException ex) {
ErrorResponse error = new ErrorResponse(
"DATOS_INVALIDOS",
ex.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
}
Creación de respuestas de error estructuradas
Para mantener consistencia en las respuestas de error, es recomendable crear una clase que represente la estructura estándar de los errores:
public class ErrorResponse {
private String codigo;
private String mensaje;
private LocalDateTime timestamp;
public ErrorResponse(String codigo, String mensaje, LocalDateTime timestamp) {
this.codigo = codigo;
this.mensaje = mensaje;
this.timestamp = timestamp;
}
// Getters y setters
public String getCodigo() { return codigo; }
public void setCodigo(String codigo) { this.codigo = codigo; }
public String getMensaje() { return mensaje; }
public void setMensaje(String mensaje) { this.mensaje = mensaje; }
public LocalDateTime getTimestamp() { return timestamp; }
public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
}
Manejo de múltiples tipos de excepciones
Un controlador de excepciones global puede manejar diferentes tipos de errores con métodos específicos para cada caso:
@RestControllerAdvice
public class GlobalExceptionHandler {
// Errores de validación de Spring
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> manejarValidacionCampos(MethodArgumentNotValidException ex) {
StringBuilder mensaje = new StringBuilder("Errores de validación: ");
ex.getBindingResult().getFieldErrors().forEach(error ->
mensaje.append(error.getField()).append(" - ").append(error.getDefaultMessage()).append("; ")
);
ErrorResponse error = new ErrorResponse(
"VALIDACION_FALLIDA",
mensaje.toString(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
// Errores de conversión de tipos
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<ErrorResponse> manejarTipoIncorrecto(MethodArgumentTypeMismatchException ex) {
String mensaje = String.format("El parámetro '%s' debe ser de tipo %s",
ex.getName(), ex.getRequiredType().getSimpleName());
ErrorResponse error = new ErrorResponse(
"TIPO_PARAMETRO_INCORRECTO",
mensaje,
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
// Captura general para excepciones no manejadas
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> manejarErrorGeneral(Exception ex) {
ErrorResponse error = new ErrorResponse(
"ERROR_INTERNO",
"Ha ocurrido un error inesperado",
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
Acceso a información de la petición
Los métodos de manejo de excepciones pueden acceder a información adicional sobre la petición HTTP que causó el error:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AccesoDenegadoException.class)
public ResponseEntity<ErrorResponse> manejarAccesoDenegado(
AccesoDenegadoException ex,
HttpServletRequest request) {
String mensaje = String.format("Acceso denegado al recurso: %s %s",
request.getMethod(), request.getRequestURI());
ErrorResponse error = new ErrorResponse(
"ACCESO_DENEGADO",
mensaje,
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(error);
}
}
Configuración de alcance específico
@RestControllerAdvice permite limitar su alcance a controladores específicos mediante atributos de configuración:
// Solo aplica a controladores en el paquete especificado
@RestControllerAdvice(basePackages = "com.ejemplo.api.controladores")
public class ApiExceptionHandler {
// Métodos de manejo de excepciones
}
// Solo aplica a controladores específicos
@RestControllerAdvice(assignableTypes = {UsuarioController.class, ProductoController.class})
public class EspecificoExceptionHandler {
// Métodos de manejo de excepciones
}
Esta flexibilidad permite crear diferentes estrategias de manejo de errores para distintas partes de la aplicación, manteniendo la separación de responsabilidades y facilitando el mantenimiento del código.
Otras 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
Introducción Y Entorno
Spring Boot Starters
Introducción Y Entorno
Inyección De Dependencias
Introducción Y Entorno
Crear Proyecto Con Spring Initializr
Introducción Y Entorno
Crear Proyecto Desde Visual Studio Code
Introducción Y Entorno
Controladores Spring Mvc
Spring Mvc Con Thymeleaf
Vista En Spring Mvc Con Thymeleaf
Spring Mvc Con Thymeleaf
Controladores Spring Rest
Spring Mvc Con Thymeleaf
Open Api Y Cómo Agregarlo En Spring Boot
Spring Mvc Con Thymeleaf
Servicios En Spring
Spring Mvc Con Thymeleaf
Clientes Resttemplate Y Restclient
Spring Mvc Con Thymeleaf
Rxjava En Spring Web
Spring Mvc Con Thymeleaf
Métodos Post En Controladores Mvc
Spring Mvc Con Thymeleaf
Métodos Get En Controladores Mvc
Spring Mvc Con Thymeleaf
Formularios En Spring Mvc
Spring Mvc Con Thymeleaf
Crear Proyecto Con Intellij Idea
Spring Mvc Con Thymeleaf
Introducción A Los Modelos Mvc
Spring Mvc Con Thymeleaf
Layouts Y Fragmentos En Thymeleaf
Spring Mvc Con Thymeleaf
Estilización Con Bootstrap Css
Spring Mvc Con Thymeleaf
Gestión De Errores Controlleradvice
Spring Mvc Con Thymeleaf
Estilización Con Tailwind Css
Spring Mvc Con Thymeleaf
Introducción A Controladores Rest
Spring Rest
Métodos Get En Controladores Rest
Spring Rest
Métodos Post En Controladores Rest
Spring Rest
Métodos Delete En Controladores Rest
Spring Rest
Métodos Put Y Patch En Controladores Rest
Spring Rest
Gestión De Errores Restcontrolleradvice
Spring Rest
Creación De Entidades Jpa
Spring Data Jpa
Asociaciones De Entidades Jpa
Spring Data Jpa
Repositorios Spring Data
Spring Data Jpa
Métodos Find En Repositorios
Spring Data Jpa
Inserción De Datos
Spring Data Jpa
Actualizar Datos De Base De Datos
Spring Data Jpa
Borrar Datos De Base De Datos
Spring Data Jpa
Consultas Jpql Con @Query En Spring Data Jpa
Spring Data Jpa
Api Query By Example (Qbe)
Spring Data Jpa
Api Specification
Spring Data Jpa
Repositorios Reactivos
Spring Data Jpa
Configuración Base De Datos Postgresql
Spring Data Jpa
Configuración Base De Datos Mysql
Spring Data Jpa
Introducción A Jpa Y Spring Data Jpa
Spring Data Jpa
Configuración Base De Datos H2
Spring Data Jpa
Testing Unitario De Componentes Y Servicios
Testing Con Spring Test
Testing De Repositorios Spring Data Jpa
Testing Con Spring Test
Testing Controladores Spring Mvc Con Thymeleaf
Testing Con Spring Test
Testing Controladores Rest Con Json
Testing Con Spring Test
Testing De Aplicaciones Reactivas Webflux
Testing Con Spring Test
Testing De Seguridad Spring Security
Testing Con Spring Test
Testing Con Apache Kafka
Testing Con Spring Test
Introducción Al Testing
Testing Con Spring Test
Introducción A Spring Security
Seguridad Con Spring Security
Seguridad Basada En Formulario
Seguridad Con Spring Security
Registro De Usuarios En Api Rest
Seguridad Con Spring Security
Login De Usuarios En Api Rest
Seguridad Con Spring Security
Validación Jwt En Api Rest
Seguridad Con Spring Security
Autenticación Jwt Completa En Api Rest
Seguridad Con Spring Security
Seguridad Jwt En Api Rest Reactiva Spring Webflux
Seguridad Con Spring Security
Autenticación Y Autorización Con Anotaciones
Seguridad Con Spring Security
Fundamentos De Autenticación Oauth
Seguridad Con Spring Security
Autenticación Oauth Con Github
Seguridad Con Spring Security
Testing Con Spring Security Test
Seguridad Con Spring Security
Autenticación Oauth En Api Rest
Seguridad Con Spring Security
Introducción A Spring Webflux
Reactividad Webflux
Spring Data R2dbc
Reactividad Webflux
Controlador Reactivo Basado En Anotaciones
Reactividad Webflux
Controlador Reactivo Basado En Funciones
Reactividad Webflux
Operadores Reactivos Básicos
Reactividad Webflux
Operadores Reactivos Avanzados
Reactividad Webflux
Cliente Reactivo Webclient
Reactividad Webflux
Introducción E Instalación De Apache Kafka
Mensajería Asíncrona
Crear Proyecto Con Apache Kafka
Mensajería Asíncrona
Creación De Producers
Mensajería Asíncrona
Creación De Consumers
Mensajería Asíncrona
Kafka Streams En Spring Boot
Mensajería Asíncrona
Integración Con Angular
Integración Frontend
Integración Con React
Integración Frontend
Integración Con Vue
Integración Frontend
Ejercicios de programación de SpringBoot
Evalúa tus conocimientos de esta lección Gestión de errores RestControllerAdvice con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Crear entidades JPA
Controladores Spring MVC
Asociaciones de entidades JPA
Creación de entidades
Reto servicio PedidoService
Reto controlador REST
Consultas JPQL
Reto test controlador REST
Anotaciones JPA
Relación ManyToOne con Tarea y Proyecto
CRUD Customers Spring MVC + Spring Data JPA
Backend API REST con Spring Boot
Filtrar categorías por nombre
Reto controlador MVC Categoría
Entidad y repositorio
Métodos derivados y consultas JPQL en repositorios
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el uso básico de @ExceptionHandler para manejar excepciones en controladores individuales.
- Aprender a centralizar el manejo de errores en toda la aplicación con @RestControllerAdvice.
- Diseñar respuestas de error estructuradas y consistentes para APIs REST.
- Implementar manejo de múltiples tipos de excepciones específicas y generales.
- Configurar el alcance de @RestControllerAdvice para aplicar el manejo de errores a controladores específicos o paquetes.