Curso de Spring Boot
Cuando creamos APIs es muy importante validar los datos que envían los usuarios.
Si no validamos los datos pueden ocurrir problemas como:
- datos vacíos
- emails incorrectos
- números negativos
- información inválida en la base de datos
Spring Boot permite validar datos fácilmente usando Jakarta Validation.
8.1 Añadir dependencia de validación
En pom.xml añadimos:
1<dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-validation</artifactId> 4</dependency>
Esto habilita las anotaciones de validación.
8.2 Validar usando anotaciones
Spring permite validar los campos usando anotaciones.
Ejemplo:
1public class UserDTO { 2 3 @NotBlank 4 private String name; 5 6 @Email 7 private String email; 8 9}
Qué significa
| anotación | función |
|---|---|
@NotNull | no puede ser null |
@NotBlank | no puede estar vacío |
@Email | debe ser email válido |
@Size | tamaño mínimo/máximo |
@Min | valor mínimo |
@Max | valor máximo |
8.3 Ejemplo completo DTO validado
1import jakarta.validation.constraints.Email; 2import jakarta.validation.constraints.NotBlank; 3import jakarta.validation.constraints.Size; 4 5public class UserDTO { 6 7 @NotBlank(message = "El nombre es obligatorio") 8 private String name; 9 10 @Email(message = "Email inválido") 11 private String email; 12 13 @Size(min = 6, message = "La contraseña debe tener al menos 6 caracteres") 14 private String password; 15 16}
8.4 Activar validación en el Controller
Para que Spring valide los datos debemos usar:
1@Valid
Ejemplo
1@PostMapping("/users") 2public String createUser(@Valid @RequestBody UserDTO user) { 3 4 return "Usuario creado"; 5 6}
8.5 Ejemplo petición correcta
Petición:
1{ 2 "name": "Ana", 3 "email": "ana@email.com", 4 "password": "123456" 5}
Resultado:
1Usuario creado
8.6 Ejemplo petición incorrecta
Petición:
1{ 2 "name": "", 3 "email": "correo_invalido", 4 "password": "123" 5}
Respuesta automática de Spring:
1{ 2 "errors": [ 3 "El nombre es obligatorio", 4 "Email inválido", 5 "La contraseña debe tener al menos 6 caracteres" 6 ] 7}
8.7 Anotaciones de validación más usadas
@NotNull
No permite valores nulos.
1@NotNull 2private Integer age;
@NotBlank
No permite texto vacío.
1@NotBlank 2private String name;
@Email
Valida emails.
1@Email 2private String email;
@Size
Define tamaño mínimo y máximo.
1@Size(min = 3, max = 20) 2private String username;
@Min y @Max
Validan números.
1@Min(18) 2private int age;
8.8 Validar parámetros de URL
También podemos validar parámetros.
Ejemplo
1@GetMapping("/users/{id}") 2public String getUser(@PathVariable @Min(1) Long id) { 3 4 return "Usuario " + id; 5 6}
Si enviamos:
1/users/0
Spring devolverá error.
8.9 Manejo global de errores de validación
Por defecto Spring devuelve errores simples.
Podemos mejorar la respuesta usando:
1@ControllerAdvice
Ejemplo
1@ControllerAdvice 2public class ValidationHandler { 3 4 @ExceptionHandler(MethodArgumentNotValidException.class) 5 public ResponseEntity<Map<String, String>> handleValidationErrors( 6 MethodArgumentNotValidException ex) { 7 8 Map<String, String> errors = new HashMap<>(); 9 10 ex.getBindingResult().getFieldErrors() 11 .forEach(error -> errors.put( 12 error.getField(), 13 error.getDefaultMessage() 14 )); 15 16 return ResponseEntity.badRequest().body(errors); 17 18 } 19 20}
8.10 Ejemplo respuesta mejorada
Si hay errores:
1{ 2 "name": "El nombre es obligatorio", 3 "email": "Email inválido", 4 "password": "La contraseña debe tener al menos 6 caracteres" 5}
Esto es mucho más claro para el cliente.
8.11 Validaciones personalizadas
También podemos crear nuestras propias validaciones.
Ejemplo:
1@Target({ElementType.FIELD}) 2@Retention(RetentionPolicy.RUNTIME) 3@Constraint(validatedBy = PhoneValidator.class) 4public @interface ValidPhone { 5 6 String message() default "Teléfono inválido"; 7 8}
Y crear el validador:
1public class PhoneValidator implements ConstraintValidator<ValidPhone, String> { 2 3 public boolean isValid(String phone, ConstraintValidatorContext context) { 4 5 return phone != null && phone.matches("[0-9]{9}"); 6 7 } 8 9}
8.12 Buenas prácticas
Validar siempre en DTO
No validar en entidades.
Usar mensajes claros
Ejemplo:
1@NotBlank(message="El nombre es obligatorio")
No confiar en el cliente
Aunque el frontend valide, el backend también debe hacerlo.
- Loading...