📘Custom Exception을 활용하여 에러 메세지를 직접 남겨준다.
@Getter
@AllArgsConstructor
public enum ErrorCode {
USER_ALREADY_EXISTS(HttpStatus.CONFLICT, "이미 존재하는 사용자입니다."),
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "유저 정보가 없습니다.");
private final HttpStatus httpStatus
private final String message;
}
CustomException 클래스를 생성해준다.RuntimeException을 상속받는다.@Getter
public class CustomException extends RuntimeException{
private final HttpStatus status;
public CustomException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.status= errorCode.getStatus();
}
}
Dto 를 생성해준다.status 는 상태코드의 int 값만 받기 위해 int로 선언해준다.location 도 만들어준다.@Getter
public class ExceptionDto {
private final int status;
private final String message;
private final String location;
public ExceptionDto(HttpStatus status, String message, String location) {
this.status = status.value();
this.message = message;
this.location = location;
}
}
@RestControllerAdvice를 통해 @ExceptionHandler 메서드를 등록하여, API 내의 예외들을 일괄 처리할 수 있도록해준다.Custom 예외만 처리하고 있지만, CustomException으로 직접 날릴 수 없는 예외들은 따로 지정하여 처리가 가능하다.@RestControllerAdvice
public class GlobalExceptionHandler{
//다른 예외도 등록하여 처리가 가능하다.
@ExceptionHandler(CustomException.class)
public ResponseEntity<ExceptionDto> handleCustomException(CustomException e){
String location = getExceptionOccurredLocation(e);
ExceptionDto exceptionDto = new ExceptionDto(e.getStatus(), e.getMessage(), location);
return ResponseEntity.status(e.getStatus()).body(exceptionDto);
}
//location 구하는 메서드
private String getExceptionOccurredLocation(Throwable e) {
if (e == null || e.getStackTrace().length == 0) return "Unknown Location";
StackTraceElement element = e.getStackTrace()[0];
String className = element.getClassName().substring(element.getClassName().lastIndexOf('.') + 1);
return className + "." + element.getMethodName() + " :: Line " + element.getLineNumber();
}
}
CustomException을 생성해 준다.User user = userRepository.findById(id)
.orElseThrow(()-> new CustomException(ErrorCode.USER_NOT_FOUND));
404 Not Found 에러와 함께 DTO 타입으로 전달된 객체가 JSON 방식으로 반환된다.