SpringBoot Exception 처리2

devdo·2022년 3월 23일
0

SpringBoot

목록 보기
20/35
post-thumbnail

https://velog.io/@mooh2jj/spring-boot-Exception-처리 외에
Exception 처리에 대해서 customize한 Excetption 클래스들을 소개합니다.


ErrorDetails

@AllArgsConstructor
@Getter
public class ErrorDetails {

    private Date timestamp;
    private String message;
    private String details;

}

RuntimeException 상속한 커스터마이징한 Exception들

1) ResourceNotFoundException(NotFount용 Exception)

NotFound용 Exception 은
ResponseStatusException(HttpStatus.NOT_FOUND)) 가 따로 있습니다. 이를 커스터마이징하는 것입니다.

@Getter
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException{

    private final String resourceName;
    private final String fieldName;

    public ResourceNotFoundException(String resourceName, String fieldName, long fieldValue) {
        super(String.format("%s not found with %s: %d", resourceName, fieldName, fieldValue)); // Post not found with postId : 55
        this.resourceName = resourceName;
        this.fieldName = fieldName;
    }

}

2) BlogAPIException

@Getter
public class BlogAPIException extends RuntimeException {

    private HttpStatus status;
    private String message;

    public BlogAPIException(HttpStatus status, String message) {
        this.status = status;
        this.message = message;
    }
}

ExceptionHandler

BlogExceptionHandler

  • Specific: @ExceptionHandler에서 특정 Exception 클래스를 골라주면 됩니다.

  • Gloabl : @ExceptionHandler에서 Exception 클래스만 골라주면 됩니다.

  • log.error 로그처리도 여기서 할 수 있습니다.

<log.error가 나는 콘솔 모습>

@ControllerAdvice
public class BlogExceptionHandler extends ResponseEntityExceptionHandler {

    // handle sepecific exceptions
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorDetails> handleResourceNotFoundException(
            ResourceNotFoundException exception,
            WebRequest webRequest){
		log.error("ResourceNotFoundException", exception);	// log처리를 여기서!

        ErrorDetails errorDetails = new ErrorDetails(
                new Date(),
                exception.getMessage(),
                webRequest.getDescription(false));

        return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(BlogAPIException.class)
    public ResponseEntity<ErrorDetails> handleBlogAPIException(
            BlogAPIException exception,
            WebRequest webRequest){
		log.error("BlogAPIException", exception);
        
        ErrorDetails errorDetails = new ErrorDetails(
                new Date(),
                exception.getMessage(),
                webRequest.getDescription(false));

        return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
    }

    // global exception
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorDetails> handleGlobalException(
            Exception exception,
            WebRequest webRequest){
		log.error("Exception", exception);
        
        ErrorDetails errorDetails = new ErrorDetails(
                new Date(),
                exception.getMessage(),
                webRequest.getDescription(false));

        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }

결과 화면


BlogServiceImpl

	// exception 처리 메서드
    private Comment errorCheckComment(BoardRepository boardRepository, Long boardId, CommentRepository commentRepository, Long commentId) {
        Board board = boardRepository.findById(boardId)
                .orElseThrow(() -> new ResourceNotFoundException("Board", "id", boardId));

        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new ResourceNotFoundException("Comment", "id", commentId));

        if (!comment.getBoard().getId().equals(board.getId())) {
            throw new BlogAPIException(HttpStatus.BAD_REQUEST, "comment가 board에 속하지 않습니다!");
        }
        return comment;
    }

BindingResult(Vaildation 처리)

똑같이 GlobalExceptionHandler 안에서 메서드로 만들어주었습니다.
vaildation 예외 처리라면 Exception은 MethodArgumentNotValidException입니다.

Validation 처리는 이 블로그와도 참고하시기 바랍니다.
https://velog.io/@mooh2jj/Spring-Boot-Validation-적용하는-법

    //BindingResult Validation 처리
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers,
                                                                  HttpStatus status,
                                                                  WebRequest request) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String message = error.getDefaultMessage();
            errors.put(fieldName, message);
        });

        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }

}


참고

profile
배운 것을 기록합니다.

0개의 댓글