Рубрики
Без рубрики

Обработка ошибок пользовательских аннотаций Javax в Spring

Привет! В этой статье я расскажу, как переопределить метод обработчика исключений по умолчанию для метода… Помеченный как spring, spring boot, java, проверка.

Привет! В этой статье я расскажу, как переопределить метод обработчика исключений по умолчанию для 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 ResponseEntity saveUser(@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 handleUserMethodFieldErrors(MethodArgumentNotValidException ex, WebRequest request) {  
    // some logic
}

Бросает аннотации Javax MethodArgumentNotValidException.class итак, отменил это исключение. В методе извлеките ошибки полей и создайте из них объекты Custom Field Error .

final List fieldErrors = 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”