Привет! В этой статье я расскажу, как переопределить метод обработчика исключений по умолчанию для MethodArgumentNotValidException
, который генерируется при нарушении аннотаций проверки Java Bean.
Что такое проверка Java Bean?
Проверка Java Bean – это спецификация, которая определена в JSR-380 . Это позволяет определять ограничения с помощью аннотаций, писать пользовательские ограничения и т.д. Я буду использовать Hibernate Validator , поскольку это единственная сертифицированная реализация Bean Validation 2.0. Это не обязательно использовать с Spring, но я собираюсь реализовать его с помощью Spring Boot из-за его популярности. Я не буду объяснять, как использовать эти аннотации, однако вы можете найти их в одной из моих статей .
Создайте простой проект и предоставьте несколько Аннотаций
Создайте проект с помощью Spring Initializr и выберите зависимости Web и Lombok. Потому что web-starter включает в себя средство проверки гибернации. Затем создайте класс с именем User, как показано ниже.
@Data public class User { @Length(min = 2, max = 30, message = "Name must be between 2-30 characters. ") @Pattern(regexp = "^[a-zA-Z]+(([',. -][a-zA-Z])?[a-zA-Z]*)*$", message = "Name is invalid.") private String name; @Length(min = 2, max = 30, message = "Surname must be between 2-30 characters.") @Pattern(regexp = "^[a-zA-Z]+(([',. -][a-zA-Z])?[a-zA-Z]*)*$", message = "Surname is invalid.") private String surname; @Email(message = "Enter a valid email address.") private String email;
Для сообщений об ошибках лучше использовать внешний источник сообщений но я не использовал его, потому что это сделало бы эту статью длиннее.
Затем создайте RestController и примите пользователя в качестве @Valid
ввода.
@RestController @RequestMapping("/api/users") public class UserRestController { @PostMapping public ResponseEntitysaveUser(@Valid @RequestBody User user) { return ResponseEntity.ok(user); } }
Не забудьте использовать @Valid
аннотацию. Потому что это гарантирует, что аннотированный параметр проверен.
Запустите приложение и отправьте пример запроса. (Конечно, вам не обязательно использовать cURL. Я отправил этот запрос с почтальоном. Вы можете просто скопировать это и импортировать в Postman в виде необработанного текста.)
curl --location --request POST 'http://localhost:8080/api/users' \ --header 'Content-Type: application/json' \ --data-raw '{ "name": "Marion", "surname": "Cotillard", "email": "marion@cotillard.com", "birthdate": "1975-09-30" }'
Этот запрос вернет 200, как и следовало ожидать. А теперь давайте нарушим некоторые правила:
curl --location --request POST 'http://localhost:8080/api/users' \ --header 'Content-Type: application/json' \ --data-raw '{ "name": "M", "surname": "Cotillard", "email": "marion@cotillard.com", "birthdate": "1975-09-30" }'
Я только что нарушил правило @Length
для поля name
. На этот запрос последовал длинный ответ:
{ "timestamp": "2020-02-01T21:27:06.935+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "Length.user.name", "Length.name", "Length.java.lang.String", "Length" ], "arguments": [ { "codes": [ "user.name", "name" ], "arguments": null, "defaultMessage": "name", "code": "name" }, 30, 2 ], "defaultMessage": "Name must be between 2-30 characters. ", "objectName": "user", "field": "name", "rejectedValue": "M", "bindingFailure": false, "code": "Length" } ], "message": "Validation failed for object='user'. Error count: 1", "path": "/api/users" }
Это может привести к путанице в ответе, но можно создать пользовательский ответ.
Переопределить Обработчик исключений
Во-первых, создайте POJO для пользовательского ответа.
@Getter @Setter @Builder @AllArgsConstructor public class CustomFieldError { private String field; private String message; }
Вы можете добавить дополнительные поля, но этого достаточно для данной статьи. Затем создайте метод обработчика исключений:
@ExceptionHandler(MethodArgumentNotValidException.class) public final ResponseEntity
Бросает аннотации Javax MethodArgumentNotValidException.class
итак, отменил это исключение. В методе извлеките ошибки полей и создайте из них объекты Custom Field Error
.
final ListfieldErrors = ex.getBindingResult().getFieldErrors(); final List customFieldErrors = new ArrayList<>(); for (FieldError fieldError : fieldErrors) { final String field = fieldError.getField(); final String message = fieldError.getDefaultMessage(); final CustomFieldError customFieldError = CustomFieldError.builder().field(field).message(message).build(); customFieldErrors.add(customFieldError); }
Вы также можете получить отклоненное значение
и
Код ошибки
return ResponseEntity.badRequest().body(customFieldErrors);
Запустите проект еще раз и отправьте тот же запрос. Это вернет ответ 400 с приведенным ниже текстом:
[ { "field": "name", "message": "Name must be between 2-30 characters. " } ]
Вы можете настроить этот ответ или переопределить аналогичные обработчики исключений с помощью того же подхода.
Репозиторий Github: Репозиторий Github:
По вопросам, предложениям или исправлениям, не стесняйтесь обращаться ко мне по:
Электронная почта: kamer@kamerelciyar.com Твиттер: Твиттер:
Оригинал: “https://dev.to/kamer/custom-javax-annotation-error-handling-in-spring-5a03”