JavaRush /Java Blog /Random-KO /스프링 부트 컨트롤러의 예외 처리
Павел
레벨 11

스프링 부트 컨트롤러의 예외 처리

Random-KO 그룹에 게시되었습니다
기사주기의 목차 다시 한번 안녕하세요! 이제 키보드의 먼지를 털어낼 시간입니다. 스프링 부트 프로젝트를 생성합니다. Maven 종속성에서 다음이 필요합니다.
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <java.version>1.8</java.version>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.0.RELEASE</version>
    <relativePath/><!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
스프링 부트 컨트롤러의 예외 처리 - 1 더 읽기 전에 BusinessException 및 CustomException 프로젝트 구조를 생성하십시오 .
public class BusinessException extends Exception{
    public BusinessException(String message) {
        super(message);
    }
}

public class CustomException extends Exception{
    public CustomException(String message) {
        super(message);
    }
}
그리고 응답 클래스
public class Response {

    private String message;

    public Response() {
    }

    public Response(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
이제 저는 귀로 트릭을 수행하고 Alexey Kutepov에게 설명을 제공할 것입니다. 그의 기사 Spring Controllers의 예외 처리 에서 그는 이러한 파일을 올바른 콘텐츠로 채우는 방법을 알려줄 것입니다. 천천히 읽고, 모든 예제를 프로젝트에 주의 깊게 복사하고, Postman에서 실행하고 테스트하세요. Alexey의 기사에서 다음 줄이 질문을 제기한 경우: generate = APPLICATION_JSON_VALUE 는 예외 처리와 아무 관련이 없으며 기본적으로 이 컨트롤러의 모든 메서드가 JSON을 반환한다고 말합니다. 필요한 경우 특정 메서드에서 이 값을 다른 MediaType으로 재정의할 수 있습니다. 읽었으면 계속 진행하세요. 위의 문서에서는 핸들러의 다양한 옵션에 대해 설명합니다. 그 중 가장 유연한 것: @ControllerAdvice - 오류 발생 시 표준 응답의 코드와 본문을 모두 변경할 수 있습니다. 또한 하나의 방법으로 여러 예외를 동시에 처리할 수 있습니다. 하지만 그게 전부는 아닙니다. 더 자세히 읽으면 향상된 @ControllerAdvice를 완전히 무료로 얻을 수 있습니다. 몇 가지 준비 작업을 해보겠습니다. 응답에 사용자 정의 오류 메시지와 표준 오류 메시지가 모두 표시되기를 원합니다. 이를 위해 Response 클래스 를 변경해 보겠습니다 . 필드를 하나 더 추가하세요.
private String debugMessage;
추가 생성자를 만들어 보겠습니다.
public Response(String message, String debugMessage) {
    this.message = message;
    this.debugMessage = debugMessage;
}
새 필드에 대한 Getter 및 Setter를 만드는 것을 잊지 마세요. 이제 요점입니다. 또 다른 컨트롤러를 작성해 봅시다:
@RestController
public class Example7Controller {
    @GetMapping(value = "/testExtendsControllerAdvice")
    public ResponseEntity<?> testExtendsControllerAdvice(@RequestBody Response response) {
        return  ResponseEntity.ok(response);
    }
}
우편 배달부에서 테스트해 보겠습니다. JSON을 http://localhost:8080/testExtendsControllerAdvice 로 보냅니다.
{
    "message": "message"
}
이에 대한 응답으로 상태 200과 본문을 받게 됩니다.
{
    "message": "message",
    "debugMessage": null
}
이제 우리는 분명히 잘못된 JSON을 보낼 것입니다
{
    11"message": "message"
}
이에 대한 응답으로 우리는 상태 400(무엇을 의미하는지 잊어버린 경우 인터넷에서 찾아보세요)과 빈 응답 본문을 받게 됩니다. 물론, 누구도 이것에 만족하지 않습니다. 싸우자. 이전에는 @ControllerAdvice를 처음부터 생성했지만 Spring Boot에는 ResponseEntityExceptionHandler 라는 템플릿이 있습니다 . 이미 NoHandlerFoundException , HttpMessageNotReadableException , MethodArgumentNotValidException 등 많은 예외를 처리하고 있습니다. 이 클래스는 오류를 처리합니다. 여기에는 여러 가지 메서드가 있으며 그 이름은 원칙 핸들 + 예외 이름을 기반으로 합니다. 몇 가지 기본적인 예외를 처리하려면 이 클래스에서 상속하고 원하는 메서드를 재정의합니다 . 기본 자문 수업을 마무리하자
@ControllerAdvice
public class DefaultAdvice extends ResponseEntityExceptionHandler {//унаследовались от обработчика-заготовки

    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Response> handleException(BusinessException e) {
        Response response = new Response(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
//Небольшое отступление: В обработчике выше, обратите внимание на HttpStatus.OK,
//он может быть и HttpStatus.BAD_REQUEST or другим, тут ограничений нет,
//попробуйте поменять статусы и потестить этот обработчик


    @Override//переопределor метод родительского класса
    protected ResponseEntity<Object> handleHttpMessageNotReadable
            (HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        Response response = new Response("Не правильный JSON",ex.getMessage());
        return new ResponseEntity<>(response, status);
    }
}
보시다시피 HttpMessageNotReadableException을 담당하는 핸들러가 재정의되었습니다 . 이 예외는 컨트롤러 메서드로 들어오는 요청 본문을 읽을 수 없는 경우(예: 잘못된 JSON) 발생합니다. handlerHttpMessageNotReadable () 메소드는 이 예외를 담당합니다 . 잘못된 JSON을 사용하여 다시 요청해 보겠습니다. http://localhost:8080/testExtendsControllerAdvice
{
    11"message": "message"
}
코드 400(잘못된 요청)과 본문이 포함된 응답을 받습니다.
{
    "message": "Не правильный JSON",
    "debugMessage": "JSON parse error: Unexpected character ('1' (code 49)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('1' (code 49)): was expecting double-quote to start field name\n at [Source: (PushbackInputStream); line: 2, column: 6]"
}
이제 응답에는 올바른 코드뿐만 아니라 정보 메시지가 포함된 본문도 포함됩니다. 올바른 JSON 요청에서 어떻게 작동하는지 확인해 보겠습니다.
{
    "message": "message"
}
우리는 다음과 같은 답변을 받았습니다.
{
    "message": "message",
    "debugMessage": null
}
솔직히 말해서 응답에 null 값이 포함된 필드가 포함되어 있는 것이 마음에 들지 않습니다 . 이제 이 문제를 빠르게 수정하겠습니다. Response 클래스 로 이동하여 필수 필드 위에 주석을 추가하세요.
@JsonInclude(JsonInclude.Include.NON_NULL)
private String debugMessage;
프로젝트를 다시 시작하고 이전 요청을 다시 수행하면 다음과 같은 응답을 받습니다.
{
    "message": "message"
}
@JsonInclude(JsonInclude.Include.NON_NULL) 주석 덕분에 이 필드는 지정된 경우에만 응답에 포함됩니다. @JsonInclude는 Jackson 주석 라이브러리 에 포함되어 있으며 , 이것이 무엇을 할 수 있는지 아는 것은 매우 유용합니다. 선택할 수 있는 두 가지 기사는 다음과 같습니다. Jackson 주석. 저자가 번역했지만 번역을 완료하지 못했습니다 . Google Translit은 훌륭한 작업을 수행합니다. 검증 검증 과 같은 개념으로 이 주제를 보완할 필요가 있습니다. 간단히 말해서, 이는 객체가 우리가 기대하는 객체인지 확인하는 것입니다. 예를 들어, "전화 번호부" 애플리케이션에서 데이터베이스에 전화번호가 있는지 확인해야 하는 경우 데이터베이스에 들어가기 전에 사용자가 숫자 대신 문자를 입력했는지 확인하는 것이 논리적입니다. 점점 복잡해지는 검증에 관한 세 가지 기사: Spring의 Bean 검증 Spring Framework에서 DTO 검증 설정 Spring Boot의 데이터 검증 오늘의 이론은 끝났습니다. 교육을 위해 다음 작업을 제안합니다. NightclubBouncer 애플리케이션을 구현해야 합니다. 요구 사항: 1) 애플리케이션은 JSON을 입력으로 수락하고 데이터베이스에 써야 합니다. JSON 예:
{
    "name": "Katy Perry"
    “status”:super star”
}
그리고 응답 본문에는 다음과 같은 문구가 포함되어야 합니다. Welcome + name ! 2) 애플리케이션은 다음 방법을 구현해야 합니다. - 데이터베이스에서 클라이언트(Postman)로 ID 별로 레코드를 출력합니다. - 필드별 레코드 삭제: name . 3) dto 레이어에서 엔터티 로 의 매핑 과 그 반대의 매핑을 구현해야 합니다 . 4) 수신 JSON의 상태 필드가 super star 와 같지 않은 경우 애플리케이션은 KickInTheAssException 오류를 발생시켜야 합니다(직접 개발해야 함). 5) KickInTheAssException 오류는 ControllerAdvice에 의해 처리되어야 하며 응답 본문에는 다음이 포함되어야 합니다. 메시지: “여기서 다시는 볼 수 없게 해주세요! 응답 상태는 400이어야 합니다. 6) 표준 오류 EntityNotFoundException . 예를 들어 Katy Perry만 클럽에 와서 ID = 1 로 데이터베이스에 저장하고 "ID별 기록 표시" 메소드를 호출하여 원하는 경우 발생합니다. 데이터베이스에 없는 id = 2 인 레코드를 표시합니다 . 이 오류는 ResponseEntityExceptionHandler 클래스 의 재정의된 메서드에 의해 처리되어야 하며 , 이 메서드는 사용자가 직접 파악해야 합니다. 응답에는 적절한 상태가 있어야 합니다. 7) 유효성 검사를 수행합니다. 간단한 옵션입니다. JSON 필드는 null이 아니거나 더 어렵습니다. "이름" 필드는 라틴 알파벳의 두 단어로 구성되어야 하며 둘 다 대문자로 시작해야 합니다. 유효하지 않은 값은 예외를 발생시키고 어떤 방식으로든 처리해야 하며 적절한 오류 코드와 오류 메시지를 인쇄해야 합니다: 유효성 검사 없음. 그리고 Lombok 라이브러리를 사용하지 않고 이 모든 것을 구현하고 프로젝트 종속성으로 포함하지 마세요 😅
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION