ErrorResponse
를 반환합니다@RestControllerAdvice
: @RestController
에서 전역적으로 발생하는 예외를 한 군데에서 처리합니다BussinessException
발생시킵니다ErrorCode Enum
을 이용해서 에러 메시지, 에러코드 및 반환할 Http Status
를 관리합니다
Http Status
값, 에러코드, 에러메시지를 관리하는 Enum 클래스@Getter
public Enum ErrorCode {
private String errorCode;
private HttpStatus httpStatus;
private String message;
ErrorCode(HttpStatus httpStatus, String errorCode, String message) {
this.httpStatus = httpStatus;
this.errorCode = errorCode;
this.message = message;
}
}
spring
에서는 transaction
을 사용하다가 unchecked exception
이 발생하면 rollback
이 되므로, RuntimeException
을 상속받아서 custom exception을 정의합니다@Getter
public class BusinessException extends RuntimeException {
private ErrorCode errorCode;
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
[com.app.global.error.ErrorResponse.java]
ErrorResponse
@Getter
@Builder
public class ErrorResponse {
private String errorCode;
private String errorMessage;
public static ErrorResponse of(String errorCode, String errorMessage) {
return ErrorResponse.builder()
.errorCode(errorCode)
.errorMessage(errorMessage)
.build();
}
public static ErrorResponse of(String errorCode, BindingResult bindingResult) {
return ErrorResponse.builder()
.errorCode(errorCode)
.errorMessage(createErrorMessage(bindingResult))
.build();
}
private static String createErrorMessage(BindingResult bindingResult) {
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
is (!isFirst) {
sb.append(",");
} else {
isFirst = false;
}
sb.append("[");
sb.append(fieldError.getField());
sb.append("]");
sb.append(fieldError.getDefaultMessage());
}
return sb.toString();
}
}
[com.app.global.error.GlobalExceptionHandler.java]
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* javax.validation.Valid 또는 @Validated binding error가 발생할 경우
*/
@ExceptionHandler(BindException.class)
protected ResponseEntity<ErrorResponse> handleBindException(BindException e) {
log.error("handleBindException", e);
ErrorResponse errorResponse = ErrorResponse.of(HttpStatus.BAD_REQUEST.toString(), e.getBindingResult());
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(errorResponse);
}
/**
* 주로 @RequestParam enum으로 binding 못했을 경우 발생
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
log.error("handleMethodArgumentTypeMismatchException", e);
ErrorResponse errorResponse = ErrorResponse.of(HttpStatus.BAD_REQUEST.toString(), e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(errorResponse);
}
/**
* 지원하지 않은 HTTP method 호출 할 경우 발생
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
protected ResponseEntity<ErrorResponse> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
log.error("handleHttpRequestMethodNotSupportedException", e);
ErrorResponse errorResponse = ErrorResponse.of(HttpStatus.METHOD_NOT_ALLOWED.toString(), e.getMessage());
return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(errorResponse);
}
/**
* 비즈니스 로직 실행 중 오류 발생
*/
@ExceptionHandler(value = { BusinessException.class })
protected ResponseEntity<ErrorResponse> handleConflict(BusinessException e) {
log.error("BusinessException", e);
ErrorResponse errorResponse = ErrorResponse.of(e.getErrorCode().getErrorCode(), e.getMessage());
return ResponseEntity.status(e.getErrorCode().getHttpStatus())
.body(errorResponse);
}
/**
* 나머지 예외 발생
*/
@ExceptionHandler(Exception.class)
protected ResponseEntity<ErrorResponse> handleException(Exception e) {
log.error("Exception", e);
ErrorResponse errorResponse = ErrorResponse.of(HttpStatus.INTERNAL_SERVER_ERROR.toString(), e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
}
}
Java Bean
유효성 검사를 사용하기 위한 스타터입력값 검증을 위한 예시 어노테이션
어노테이션 | 설명 |
---|---|
@NotEmpty | NULL 체크 및 문자열의 경우 길이 0인지 검사 |
@NotBlank | NULL 체크 및 문자열의 경우 길이 0 및 문자열 ("") 검사 |
@Length(min=, max=) | 최소, 최대 길이 검사 |
이메일 형식인지 검사 | |
@Max(숫자) | 지정한 값보다 작은지 검사 |
@Min(숫자) | 지정한 값보다 큰지 검사 |
@Null | 값이 NULL인지 검사 |
@NotNull | 값이 NULL이 아닌지 검사 |