Валидация "без участия человека" — это как иметь добросовестного робота, который проверяет вашу почту перед тем, как вы её читаете: мусор отбрасывает, важные письма отмечает. Аналогично, аннотация @Valid позволяет автоматизировать проверку входящих данных в ваших контроллерах и сервисах.
Основные аспекты @Valid
- Она является частью спецификации Bean Validation API.
- Автоматически проверяет, соответствуют ли входящие данные аннотациям валидации, объявленным в DTO (Data Transfer Object) или других объектах.
- Помогает упростить и централизовать валидацию данных, сохраняя ваш код чистым и читаемым.
Простейший пример: вы принимаете JSON как тело POST-запроса, и вам нужно, чтобы поле "email" было обязательным и соответствовало формату email. Вместо ручной проверки (например, через if) с помощью @Valid и нескольких аннотаций валидации всё это обрабатывается автоматически.
Как использовать @Valid в контроллерах?
Шаг 1. Объявление DTO
Начнём с создания DTO-класса. DTO (Data Transfer Object) — это объект, который используется для передачи данных, например, от клиента к серверу.
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
public class UserDTO {
@NotNull(message = "Имя пользователя не может быть пустым.")
@Size(min = 2, max = 30, message = "Имя пользователя должно содержать от 2 до 30 символов.")
private String username;
@NotNull(message = "Email обязателен.")
@Email(message = "Некорректный формат email.")
private String email;
public UserDTO() {}
public UserDTO(String username, String email) {
this.username = username;
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Здесь мы используем:
@NotNull— чтобы убедиться, что поле не пустое.@Size— чтобы ограничить длину строки.@Email— чтобы проверить, что email корректен.
С полем разобрались! Переходим к следующему шагу.
Шаг 2. Создание REST-контроллера
Теперь используем аннотацию @Valid в контроллере для автоматической проверки входящих данных.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
@PostMapping
public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO userDTO) {
// Если данные валидны, выполнение доходит сюда.
return new ResponseEntity<>("Пользователь успешно создан", HttpStatus.CREATED);
}
}
@RestControllerуказывает, что этот класс — REST-контроллер.@RequestBody— преобразует JSON в объектUserDTO.@Valid— запускает валидацию, которая проверяет поляUserDTO.
Если входящие данные валидны, тело запроса успешно преобразуется в объект, и сервер возвращает HTTP 201 (Created). Если валидация не прошла, Spring автоматически выбросит исключение MethodArgumentNotValidException.
Шаг 3. Добавление пользовательских сообщений
Каждая аннотация валидации в UserDTO содержит параметр message, который указывает текст ошибки. Например, если поле email не соответствует формату, клиент получит сообщение "Некорректный формат email.".
Пример приложения с использованием @Valid
Скомпонуем всё в одно небольшое приложение.
Основной код приложения
DTO:
public class UserDTO {
@NotNull(message = "Имя пользователя не может быть пустым.")
@Size(min = 2, max = 30, message = "Имя пользователя должно содержать от 2 до 30 символов.")
private String username;
@NotNull(message = "Email обязателен.")
@Email(message = "Некорректный формат email.")
private String email;
// Геттеры, сеттеры и конструктор
}
Controller:
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
@PostMapping
public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO userDTO) {
return new ResponseEntity<>("Пользователь успешно создан", HttpStatus.CREATED);
}
}
application.properties:
server.port=8080
Что, если данные не валидны?
При отправке некорректных данных Spring автоматически вернёт HTTP 400 (Bad Request) с сообщением об ошибке в формате JSON:
{
"timestamp": "2023-10-01T12:34:56.789+00:00",
"status": 400,
"error": "Bad Request",
"message": "Некорректный формат email.",
"path": "/api/users"
}
Часто встречающиеся ошибки
- Отсутствие зависимости Bean Validation в
pom.xml. В проекте может отсутствовать необходимая зависимость. Убедитесь, что в вашемpom.xmlдобавлен модуль Bean Validation:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> - Тело запроса не преобразуется в DTO. Если вы забыли указать
@RequestBody, JSON просто не будет распознан. Всегда помните об этой аннотации. - Неправильный импорт аннотации
@Valid. Убедитесь, что используетеjakarta.validation.Valid(илиjavax.validation.Validв старых версиях), а не что-то из сторонних библиотек. - Забыта обработка исключений. Spring может выбросить исключение
MethodArgumentNotValidException, которое, если не обработано, приведёт к некрасивым и запутанным сообщениям для пользователя.
Практическое применение
Валидация через @Valid широко используется в реальных проектах для:
- Автоматической проверки данных, поступающих от клиентов.
- Предотвращения ошибок на раннем этапе, до попадания данных в бизнес-логику или базу.
- Улучшения читаемости и поддержки кода.
На собеседованиях вас могут попросить описать, как вы реализуете валидацию в Spring, а ещё лучше — написать простую REST-операцию с @Valid. Знание этого инструмента даст вам серьёзное преимущество.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ