Gymterview
middle

Как работает валидация в Spring? Что такое @Valid и @Validated?

Spring интегрирует Bean Validation API (JSR 380) через Hibernate Validator для декларативной валидации данных. Аннотация @Valid перед @RequestBody активирует проверку.

Основные аннотации валидации

Пример
public class CreateUserRequest {
    @NotBlank(message = "Имя не может быть пустым")
    @Size(min = 2, max = 100)
    private String firstName;

    @NotBlank @Email
    private String email;

    @NotNull @Min(18) @Max(150)
    private Integer age;

    @Positive
    private BigDecimal balance;

    @Pattern(regexp = "^\\+7\\d{10}$")
    private String phone;

    @Past
    private LocalDate birthDate;

    @Valid @NotNull // каскадная валидация вложенного объекта
    private AddressDto address;
}

Применение

Пример
@PostMapping
public ResponseEntity<UserDto> createUser(@Valid @RequestBody CreateUserRequest request) {
    // Если валидация не пройдена -- MethodArgumentNotValidException (400)
    return ResponseEntity.status(HttpStatus.CREATED).body(userService.create(request));
}

@Valid vs @Validated

Аспект @Valid (javax) @Validated (Spring)
Группы валидации Нет Да
На уровне класса Нет Да
Каскадная валидация Да Да

Группы валидации

Пример
public interface OnCreate {}
public interface OnUpdate {}

public class UserRequest {
    @Null(groups = OnCreate.class)
    @NotNull(groups = OnUpdate.class)
    private Long id;
}

@PostMapping
public UserDto create(@Validated(OnCreate.class) @RequestBody UserRequest request) { }

@PutMapping("/{id}")
public UserDto update(@Validated(OnUpdate.class) @RequestBody UserRequest request) { }

На собеседовании: ключевое – разница между @Valid и @Validated (группы валидации). Частая ошибка – забыть @Valid перед @RequestBody (валидация не выполнится). Также – не добавить spring-boot-starter-validation (в Spring Boot 3 он не входит в starter-web).