-
에러핸들링 : GlobalExceptionHandlerSpring 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