Cómo validar datos en Spring Boot con anotaciones @Valid

En el desarrollo de aplicaciones Java con Spring Boot, una de las tareas más comunes y, a la vez, más críticas es garantizar que los datos de entrada sean correctos antes de que lleguen a la lógica de negocio. Para ello, Spring ofrece un sistema potente y elegante basado en anotaciones que permite validar datos automáticamente sin escribir lógica repetitiva.

 

 

En este post vamos a explorar cómo funcionan las validaciones en Spring Boot usando anotaciones como @Valid, @Validated, @NotNull, @Size, @NotBlank y muchas otras. Del mismo modo, también revisaremos el funcionamiento de los tags avanzados @Constraint. Veremos su uso paso a paso, con un ejemplo práctico completo que incluye entidad, controlador y respuesta ante errores.

 

¿Qué son las validaciones en Spring Boot?

 

Cuando hablamos de validación en Spring, nos referimos al proceso de comprobar si los datos que recibimos desde una petición HTTP cumplen ciertas reglas antes de procesarlos. Esto es vital para evitar errores, mantener la integridad de la información y evitar vulnerabilidades.

 

Spring Boot utiliza Java Bean Validation (JSR-380), una especificación estándar para definir restricciones directamente en los modelos. Estas restricciones se expresan mediante anotaciones que se colocan sobre los atributos de las clases, generalmente DTOs (Data Transfer Objects) o entidades.

  


Anotaciones de validación más comunes

 

✅ Anotaciones para activación de la validación

  • @Valid es una anotación del estándar JSR-380 (javax.validation) y se aplica a métodos, parámetros o propiedades para activar la validación automática.

  • @Validated es específica de Spring y se encuentra en el paquete "org.springframework.validation.annotation". Además de activar la validación, permite validar por grupos, lo cual es útil en escenarios más complejos.

Ambas sirven para lo mismo en la mayoría de los casos, aunque el tag @Validated es más versátil en proyectos avanzados.

 

 

✅ Anotaciones básicas de validación

Estas anotaciones son las validaciones específicas que se aplican a los datos. Se colocan sobre los atributos de una clase y definen reglas básicas:

  • @NotNull: El valor no puede ser "null", aunque sí puede estar vacío (por ejemplo, cadena vacía).

  • @NotBlank: Similar a @NotNull, pero en este caso sirve para validar que no vengan cadenas de texto vacías o únicamente con espacios.
  • @Size(min=, max=): Define el tamaño mínimo y máximo para cadenas o colecciones.

  • @Email: Valida que el campo tenga formato de correo electrónico.

  • @Past: Verifica que la fecha sea anterior al momento actual.


✅ Validaciones personalizadas avanzadas

Cuando las anotaciones estándar no son suficientes, puedes crear tus propias reglas de validación utilizando:

  • @Constraint: Se coloca sobre una anotación personalizada que define la validación.

  • Un validador personalizado que implementa ConstraintValidator.

Esto es útil, por ejemplo, para validar el DNI, verificar si una fecha es día laboral o si un nombre cumple una expresión regular muy específica.

 

 

🔎 Ejemplo práctico completo

 

Veamos un caso real: estamos construyendo una API REST que permite registrar usuarios. Necesitamos validar que el nombre no esté vacío, el correo tenga formato válido, la edad sea razonable y la fecha de nacimiento esté en el pasado.

 

1. Entidad con anotaciones de validación

En primer lugar, vamos a definir la entidad que va a contener las diferentes anotaciones correspondientes a las validaciones que queremos establecer sobre los distintos atributos. 
 
Importante: en el pom.xml de nuestra app debemos utilizar el módulo de validaciones de Spring: 
spring-boot-starter-validation
 
 

package com.ejemplo.validacion.model;

import jakarta.validation.constraints.*;
import java.time.LocalDate;

public class UsuarioDTO {

    @NotBlank(message = "El nombre es obligatorio")
    private String nombre;

    @Email(message = "El correo no es válido")
    @NotBlank(message = "El correo es obligatorio")
    private String correo;

    @Min(value = 18, message = "Debe ser mayor de edad")
    @Max(value = 120, message = "Edad poco realista")
    private int edad;

    @Past(message = "La fecha debe estar en el pasado")
    @NotNull(message = "La fecha de nacimiento es obligatoria")
    private LocalDate fechaNacimiento;

    // Getters y setters
}

 
 

2. Controlador REST con el tag @Valid

A continuación, nos creamos el controlador en el que vamos a tener que realizar la activación de las validaciones automáticas.
 

package com.ejemplo.validacion.controller;

import com.ejemplo.validacion.model.UsuarioDTO;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/usuarios")
public class UsuarioController {

    @PostMapping
    public ResponseEntity<?> crearUsuario(@Valid @RequestBody UsuarioDTO usuario) {
        // Si pasa la validación, simulamos respuesta de éxito
        Map<String, String> respuesta = new HashMap<>();
        respuesta.put("mensaje", "Usuario registrado correctamente");
        return ResponseEntity.ok(respuesta);
    }
}

 

 

3. Gestión de errores de validación

 

Por defecto, si hay errores, Spring lanzará una excepción de tipo "MethodArgumentNotValidException". Podemos capturarla con un gestor global para devolver una respuesta amigable:

 


package com.ejemplo.validacion.exception;

import jakarta.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handleValidaciones(MethodArgumentNotValidException ex) {
        Map<String, String> errores = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            errores.put(error.getField(), error.getDefaultMessage())
        );
        return new ResponseEntity<>(errores, HttpStatus.BAD_REQUEST);
    }
}

 

4. Ejemplo de invocación a la API (con errores)

 

Ahora ya quedarían preparadas las validaciones sobre nuestros datos de entrada. Supongamos que usamos un curl o la plataforma Postman para enviar la siguiente petición:

 

POST /api/usuarios Content-Type: application/json { "nombre": "", "correo": "sinformato", "edad": 17, "fechaNacimiento": "2050-01-01" }

 

La respuesta sería:


{ "nombre": "El nombre es obligatorio", "correo": "El correo no es válido", "edad": "Debe ser mayor de edad", "fechaNacimiento": "La fecha debe estar en el pasado" }

 

Así de claro y directo. Spring se encarga de todo el proceso de validación y únicamente necesitas definir las reglas que aplican a tus entidades.

 

 

Conclusión

 

Las validaciones mediante anotaciones en Spring Boot no sólo mejoran la calidad del código, sino que además simplifican el desarrollo al centralizar la lógica de validación en un único lugar: el modelo de datos. Usar @Valid o @Validated, junto con las anotaciones básicas y la posibilidad de crear validadores personalizados, permite crear aplicaciones más robustas y seguras sin esfuerzo adicional.

 

Este sistema es especialmente útil en aplicaciones REST, donde necesitas validar datos constantemente. Si te interesa profundizar más, te animamos a explorar también otras validaciones avanzadas como grupos y anotaciones compuestas.


¡Nos vemos en el siguiente post!

Saludos.

 

Comentarios

Entradas populares de este blog

Componentes y Ventanas de Java Swing

Configurar Apache Tomcat en Eclipse

Creación de Webservice SOAP mediante Anotaciones