spring rest app 예외 처리(global excetption handler) 방법
spring에서 잡다하게 많이 나오는 애러 정리해서 출력하기
global exception 생성하기
@ControllerAdvice // 예외 처리를 위한 annotation
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
// handle specific exceptions
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorDetails> handleResourceNotFoundException(
ResourceNotFoundException exception,
WebRequest webRequest) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), exception.getMessage(), webRequest.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(BlogApiException.class) // 사용자 정의 Exception
public ResponseEntity<ErrorDetails> handleBlogAPIException(
BlogApiException exception,
WebRequest webRequest) {
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) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), exception.getMessage(), webRequest.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
// ResponseEntityExceptionHandler 에서 찾아서
@Override // validation exception 처리
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode 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);
}
// ExceptionHandler를 이용한 방식
/** @ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException exception,
WebRequest webRequest) {
Map<String, String> errors = new HashMap<>();
exception.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError)error).getField();
String message = error.getDefaultMessage();
errors.put(fieldName, message);
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}*/
}
# 사용자 정의 exception
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
private String resourceName;
private String fieldName;
private long fieldValue;
public ResourceNotFoundException(String resourceName, String fieldName, long fieldValue) {
super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
this.resourceName = resourceName;
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
public String getResourceName() { return resourceName; }
public String getFieldName() { return fieldName; }
public long getFieldValue() { return fieldValue; }
}
public class BlogApiException extends RuntimeException {
private HttpStatus status;
private String message;
public BlogApiException(HttpStatus status, String message) {
this.status = status;
this.message = message;
}
public BlogApiException(String message, HttpStatus status, String message1) {
super(message);
this.status = status;
this.message = message1;
}
public HttpStatus getStatus(){ return status; }
}
예외처리 사용(serviceImpl) ==> 위의 GlobalExceptionHandler에서 먼저 받아서 처리
@Override
public PostDto getPostById(long id) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Post","id", id));
return mapToDto(post);
}
@Override
public PostDto updatePost(PostDto postDto, long id) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Post","id", id));
post.setContent(postDto.getContent());
post.setDescription(postDto.getDescription());
post.setTitle(postDto.getTitle());
Post savePost = postRepository.save(post);
return mapToDto(savePost);
}
@Override
public void deleteById(long id) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Post","id", id));
postRepository.delete(post);
}