ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 에러핸들링 : GlobalExceptionHandler
    Spring 2022. 4. 28. 19:59

    잘못된 요청이 들어왔을때 에러를 반환해야한다.

    에러를 분기처리 해주는 클래스를 작성하고  @RestControllerAdvice 를 붙여주면 에러 핸들링이 가능하다.

     

    GlobalExceptionHandler.java

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.validation.BindException;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.context.request.WebRequest;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
    
    @RestControllerAdvice
    @Slf4j
    public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
        //일반 에러
        @ExceptionHandler
        protected ResponseEntity<Object> handleCustomException(CustomException e) {
            return ErrorResponse.toResponseEntity(e);
        }
    
        //요청 바디 검증 실패
        @Override
        protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                      HttpHeaders headers,
                                                                      HttpStatus status,
                                                                      WebRequest request) {
            CustomException e = new CustomException(ErrorCode.BAD_REQUEST_VALIDATION, ex.getMessage());
    
            return ErrorResponse.toResponseEntity(e);
        }
    
        //모델 검증 실패
        @Override
        protected ResponseEntity<Object> handleBindException(BindException ex,
                                                             HttpHeaders headers,
                                                             HttpStatus status,
                                                             WebRequest request) {
            CustomException e = new CustomException(ErrorCode.BAD_REQUEST_VALIDATION, ex.getMessage());
            return ErrorResponse.toResponseEntity(e);
        }
    
    
    }

     

    에러를 반환해주는 ErrorResponse 가 있어야한다.

    에러 전용 dto 라고 생각하는게 맞는것같다.

     

    ErrorResponse.java

    import lombok.Builder;
    import lombok.Getter;
    import org.springframework.http.ResponseEntity;
    
    import java.time.LocalDateTime;
    
    @Getter
    @Builder
    public class ErrorResponse {
    
        private final LocalDateTime timestamp = LocalDateTime.now();
        private final int status;
        private final String error;
        private final String code;
        private final String detail;
        private final String message;
    
        public static ResponseEntity<Object> toResponseEntity(CustomException e) {
            ErrorCode errorCode = e.getErrorCode();
    
            return ResponseEntity
                    .status(errorCode.getHttpStatus())
                    .body(
                            ErrorResponse.builder()
                                    .status(errorCode.getHttpStatus().value())//httpStatus 코드
                                    .error(errorCode.getHttpStatus().name())//httpStatus 이름
                                    .code(errorCode.name())//errorCode 의 이름
                                    .detail(errorCode.getDetail())//errorCode 상세
                                    .message(e.getMessage())//에러 메시지
                                    .build()
                    );
        }
    
    }

     

    어플리케이션이 필요한 에러 코드들을 ErrorCode.java 에 모아놓았다.

    에러 코드가 한 곳에 모여있으니 찾기에도 편하고 한 눈에 보기 좋은것 같다.

    package couch.forrest.exception;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import org.springframework.http.HttpStatus;
    
    @Getter
    @AllArgsConstructor
    public enum ErrorCode {
    
        //공통 예외
        BAD_REQUEST_PARAM(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."),
        BAD_REQUEST_VALIDATION(HttpStatus.BAD_REQUEST, "검증에 실패하였습니다."),
    
        //회원 예외
        UNAUTHORIZED_USER(HttpStatus.UNAUTHORIZED, "해당 요청은 로그인이 필요합니다."),
        NOT_FOUND_USER(HttpStatus.NOT_FOUND, "해당 유저를 찾을 수 없습니다."),
        EXIST_USER(HttpStatus.BAD_REQUEST, "이미 등록된 유저입니다."),
    
        //인증 인가 예외
        FORBIDDEN_USER(HttpStatus.FORBIDDEN, "해당 요청에 권한이 없습니다."),
        INVALID_AUTHORIZATION(HttpStatus.BAD_REQUEST, "인증 정보가 부정확합니다."),
    
        //리뷰 예외
        NOT_FOUND_REVIEW(HttpStatus.NOT_FOUND, "해당 리뷰를 찾을 수 없습니다."),
        NOT_FOUND_REPLY(HttpStatus.NOT_FOUND, "해당 리뷰 찾을 수 없습니다."),
    
        //place 예외
        NOT_FOUND_PLACE(HttpStatus.NOT_FOUND, "해당 장소를 찾을 수 없습니다");
    
    
    
        private final HttpStatus httpStatus;
        private final String detail;
        }

     

    이런 식으로

    Place place = placeService.findOne(placeId)
                    .orElseThrow(() -> {
                        throw new CustomException(ErrorCode.NOT_FOUND_PLACE, "존재하지 않는 place id :" + placeId);
                    });

    에러를 반환하면

     

    Swagger로 존재하지 않는 Place id 인 0을 호출해보았다.

    ErrorResponse 에서 정의한대로 에러가 출력되는것을 알수있다.

    'Spring' 카테고리의 다른 글

    스프링부트 2.6 과 Swagger-ui 가 호환 안되는 문제  (0) 2022.04.26
    페이징 처리  (0) 2022.04.26
    API 명세서  (0) 2022.04.19
    ERD 설계  (0) 2022.04.19
    협업 프로젝트 시작  (0) 2022.03.22
Designed by Tistory.