diff --git a/src/main/java/com/server/capple/global/exception/ControllerAdvice.java b/src/main/java/com/server/capple/global/exception/ControllerAdvice.java index 2afb4bc9..936f77dc 100644 --- a/src/main/java/com/server/capple/global/exception/ControllerAdvice.java +++ b/src/main/java/com/server/capple/global/exception/ControllerAdvice.java @@ -2,16 +2,27 @@ import com.server.capple.global.common.BaseResponse; import com.server.capple.global.exception.errorCode.GlobalErrorCode; +import jakarta.validation.ConstraintViolationException; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Optional; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.WebRequest; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.NoHandlerFoundException; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; -@RestController -public class ControllerAdvice { +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ControllerAdvice extends ResponseEntityExceptionHandler { /** * 정의한 RestApiException 예외 처리 @@ -24,7 +35,7 @@ public ResponseEntity> handleRestApiException( } /** - * 일반적인 서버 에러 처리 + * 일반적인 서버 에러 예외 처리 */ @ExceptionHandler public ResponseEntity> handleException( @@ -34,16 +45,46 @@ public ResponseEntity> handleException( } /** - * MethodArgumentTypeMismatchException 발생 시 예외 처리 - * 메서드의 인자 타입이 예상과 다른 경우 + * @Validated 검증 실패 예외 처리 + */ + @ExceptionHandler(ConstraintViolationException.class) + public ResponseEntity> handleConstraintViolationException( + ConstraintViolationException e) { + return handleExceptionInternal(GlobalErrorCode.VALIDATION_ERROR.getErrorCode()); + } + + /** + * 메서드의 인자 타입이 예상과 다른 경우 예외 처리 */ @ExceptionHandler(MethodArgumentTypeMismatchException.class) - public ResponseEntity> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException e) { + public ResponseEntity> handleMethodArgumentTypeMismatch( + MethodArgumentTypeMismatchException e) { // 예외 처리 로직 return handleExceptionInternal(GlobalErrorCode.NOT_VALID_ARGUMENT_ERROR.getErrorCode()); } + /** + * @RequestBody 내부 처리 실패, + * @Valid 검증 실패한 경우 예외 처리 + */ + @Override + public ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException e, + HttpHeaders headers, + HttpStatusCode statusCode, + WebRequest request) { + Map errors = new LinkedHashMap<>(); + + e.getBindingResult().getFieldErrors().stream() + .forEach(fieldError -> { + String fieldName = fieldError.getField(); + String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse(""); + errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage); + }); + return handleExceptionInternalArgs(GlobalErrorCode.VALIDATION_ERROR.getErrorCode(), errors); + + } private ResponseEntity> handlerExceptionInternal( ErrorCode errorCode) { @@ -58,7 +99,7 @@ private ResponseEntity> handleExceptionInternal(ErrorCode e .body(BaseResponse.onFailure(errorCode.getCode(), errorCode.getMessage(), null)); } - private ResponseEntity handlerExceptionInternalArgs( + private ResponseEntity handleExceptionInternalArgs( ErrorCode errorCode, Map errorArgs) { return ResponseEntity diff --git a/src/main/java/com/server/capple/global/exception/errorCode/GlobalErrorCode.java b/src/main/java/com/server/capple/global/exception/errorCode/GlobalErrorCode.java index d7229569..3686e7a8 100644 --- a/src/main/java/com/server/capple/global/exception/errorCode/GlobalErrorCode.java +++ b/src/main/java/com/server/capple/global/exception/errorCode/GlobalErrorCode.java @@ -16,6 +16,7 @@ public enum GlobalErrorCode implements ErrorCodeInterface { SERVER_ERROR("GLOBAL005", "서버 에러, 관리자에게 문의해주세요.", HttpStatus.INTERNAL_SERVER_ERROR), ACCESS_DENIED("GLOBAL006", "올바르지 않은 권한입니다.", HttpStatus.FORBIDDEN), NOT_VALID_ARGUMENT_ERROR("GLOBAL007", "올바르지 않은 Argument Type입니다.", HttpStatus.BAD_REQUEST), + VALIDATION_ERROR("GLOBAL007", "Validation Error입니다.", HttpStatus.BAD_REQUEST), ; private final String code;