์คํ๋ง์์ ์๋ฌ ํธ๋ค๋ง์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ธ @ExceptionHandler์ ๋ํด์ ์์๋ณด์.
@RestController
public class SimpleController {
// ...
@ExceptionHandler(value = IllegalArgumentException.class)
public ResponseEntity<String> invokeError(IllegalArgumentException e) {
...
return new ResponseEntity<>("error Message", HttpStatus.BAD_REQUEST);
}
}
์ฌ๋ฌ๊ฐ์ Exception์ ์ก์์ผํ๋ค๋ฉด, @ExceptionHandler(IOException.class)
์ฒ๋ผ ํฌ๊ด์ ์ธ๊ฒ ์๋ @ExceptionHandler(FileSystemException.class, RemoteException.class)
๋ก ๊ตฌ์ฒด์ ์ผ๋ก ๋ช
์ํด์ฃผ๋ ๊ฒ์ ๊ถ์ฅํ๋ค๊ณ ํ๋ค.
ํ๋์ ํด๋์ค๋ก ๋ชจ๋ ์ปจํธ๋กค๋ฌ์ ๋ํด ์ ์ญ์ ์ผ๋ก ์์ธ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํจ
์ง์ ์ ์ํ ์๋ฌ ์๋ต์ ์ผ๊ด์ฑ์๊ฒ ํด๋ผ์ด์ธํธ์๊ฒ ๋ด๋ ค์ค ์ ์์
๋ณ๋์ try-catch๋ฌธ์ด ์์ด ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ๋์์ง
ํ ํ๋ก์ ํธ๋น ํ๋์ ControllerAdvice๋ง ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค.
๋ง์ฝ ์ฌ๋ฌ ControllerAdvice๊ฐ ํ์ํ๋ค๋ฉด basePackages๋ annotations ๋ฑ์ ์ง์ ํด์ผ ํ๋ค.
์ง์ ๊ตฌํํ Exception ํด๋์ค๋ค์ ํ ๊ณต๊ฐ์์ ๊ด๋ฆฌํ๋ค.
@JsonFormat(shape = Shape.OBJECT) //์ง๋ ฌํํ ๋ ์ด๋ค ๊ฐ์ ๋ชจ์ต์ผ๋ก ์ง๋ ฌํ๋ ์ง
@RequiredArgsConstructor // ํ์(final)๋ณ์ ํ๋ผ๋ฏธํฐ๋ก ๊ฐ์ง๋ ์์ฑ์ ์์ฑ
@Getter
public enum ErrorCode {// enum ํด๋์ค
//Common -> http ์์ฒญ์ ๋ฐ์ํ ๋งํ ์์ธ
INVALID_INPUT_VALUE(HttpStatus.BAD_REQUEST, "Common-001", " Invalid Input Value"),
METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "Common-002", " Invalid Http Method"),
ENTITY_NOT_FOUND(HttpStatus.BAD_REQUEST,"Common-003", " Entity Not Found"),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Common-004", "Server Error"),
INVALID_TYPE_VALUE(HttpStatus.BAD_REQUEST,"Common-005", " Invalid Type Value"),
HANDLE_ACCESS_DENIED(HttpStatus.FORBIDDEN, "Common-006", "Access is Denied"),
//Member Validation
EMAIL_DUPLICATION(HttpStatus.BAD_REQUEST, "Member-001", "Email is Duplication"),
LOGIN_INPUT_INVALID(HttpStatus.BAD_REQUEST, "Member-002", "Login input is invalid"),
//room Validation
//...๋ฑ
;
private final HttpStatus status; // http ์ํ์ฝ๋
private final String code;//์๋ฌ์ฝ๋
private final String message;//์๋ฌ๋ฉ์์ง
}
@Getter
public class BusinessException extends RuntimeException{ //api ๋ด๋ถ๋์ํ ๋(๋น์ฆ๋์ค ๋ก์ง์์) ๋ฐ์ํ๋ ์ผ๋ฐ์ ์ธ ์์ธ๋ค
private final ErrorCode errorCode;
public BusinessException(String message, ErrorCode errorCode) {
super(message);
this.errorCode = errorCode;
}
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
}
@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice {
/*
@Valid ๋๋ @Validated๋ก binding error ๋ฐ์์ ๋ฐ์ํ๋ ์์ธ
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException e) {
log.warn("handleMethodArgumentNotValidException", e);
final ErrorResponse response = ErrorResponse.of(ErrorCode.INVALID_INPUT_VALUE,
e.getBindingResult());
return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
}
/*
enum type์ด ์ผ์นํ์ง ์์ binding ๋ชปํ ๊ฒฝ์ฐ ๋ฐ์
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentTypeMismatchException(
MethodArgumentTypeMismatchException e) {
log.error("handleMethodArgumentTypeMismatchException", e);
final ErrorResponse response = ErrorResponse.of(e);
return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
}
/*
์ง์ํ์ง ์์ Http Method๋ฐฉ์์ผ๋ก ํธ์ถํ ๊ฒฝ์ฐ ๋ฐ์
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
HttpRequestMethodNotSupportedException e) {
log.error("handleHttpRequestMethodNotSupportedException", e);
final ErrorResponse response = ErrorResponse.of(ErrorCode.METHOD_NOT_ALLOWED);
return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
}
@ExceptionHandler(BusinessException.class) //๋น์ฆ๋์ค๋ก์ง์์ ๋์ ธ์ง๋,๋ฐ์๋๋ ์์ธ๋ค์ ๋ํ ์ฒ๋ฆฌ (validation์ค๋ฅ๋ค๊ณผ ๊ฐ์)
protected ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
log.error("handle๋ด๋ถ๋ก์ง์๋ฌ(BusinessException)", e);
final ErrorCode code = e.getErrorCode();
final ErrorResponse response = ErrorResponse.of(code);
return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
}
@ExceptionHandler(Exception.class) // ์์ ์์ธ๋ค์์ ๊ฑธ๋ฌ์ง์ง์์ ๋๋จธ์ง ์์ธ๋ค์ ๋ํ ์ฒ๋ฆฌ
protected ResponseEntity<ErrorResponse> handleException(Exception e) {
log.error("handleAllException", e);
final ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR);
return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus()));
}
}
์ถ์ฒ: https://mangkyu.tistory.com/204 [MangKyu's Diary:ํฐ์คํ ๋ฆฌ]
์ถ์ฒ: https://keeeeeepgoing.tistory.com/175 [Spring] ์์ธ์ฒ๋ฆฌ (@ExceptionHandler , @ControllerAdvice,@RestControllerAdvice), ์๋ฌ์ฝ๋,์ค์ ์ ์ฉ [๋ฏธ์]