https://velog.io/@mooh2jj/spring-boot-Exception-처리 외에
Exception 처리에 대해서 customize한 Excetption 클래스들을 소개합니다.
@AllArgsConstructor
@Getter
public class ErrorDetails {
private Date timestamp;
private String message;
private String details;
}
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;
}
}
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;
}
똑같이 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);
}
}