Api는 각 시스템마다 응답 모양도 다르고, Api스펙도 모두 다르다

공통 Api 스펙을 정의하였다고 가정하자result라는 이름의 결과의 상태들을 나타내는 부분result_code : http 상태 코드result_message : 결과 메시지result_description : 결과에 대한 짧은 설명body 부분에 내가 response로 보내는 data를 @RestController을 통해 직렬화를 해서 body라는 이름으로 담아서 보내준다ArticleController나 UserController에서 일어났다고 가정을 해본다면, 두 경우 다른 Api메시지가 나가야 된다✅HandlerExceptionResolver를 사용하면 된다ExceptionResolver 이라고 한다
Exception Handler로 모이게 된다인터페이스를 이용해서 ✅Solid의 OCP원칙을 지키자!!
public interface ErrorCodeIfs {
Integer getHttpStatusCode(); // 실제 httpStatusCode
Integer getErrorCode(); // 이번 프로젝트에서 사용할 code
String getDescription(); // 설명
}

RuntimeException을 상속 받고, 인터페이스를 구현한다
OCP를 염두해둔 설계이다!!!@ExceptionHandler어노테이션을 이용해서,ExceptionHandler을 사용할 수 있다SRP원칙 위배!!!SRP원칙이 위배되는 것을 해결하기 위해서@ControllerAdvice를 사용한다@ControllerAdvice
- ControllerAdvice는 대상으로 지정한 여러 컨트롤러에서
@ExceptionHandler,@InitBinder기능을 부여해주는 역할을 한다@ControllerAdvice에 대상을 지정하지 않으면, 모든 컨트롤러에 적용된다(global 기준)@RestContollerAdvice=@ControllerAdvice+@ResponseBody- 파라미터로는
- 어노테이션을 기준으로
- 패키지명을 직접 지정
- 부모, 특정 컨트롤러를 직접 지정 할 수 있다
✅
@ExceptionHandler와@ControllerAdvice를 조합하면 예외를 깔끔하게 처리할 수 있다
@Slf4j
@RestControllerAdvice
@Order(value = Integer.MAX_VALUE)
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ResponseEntity<Api<Object>> exception(Exception e){
log.error("",e);
return ResponseEntity
.status(500)
.body(
Api.Error(ErrorCode.SERVER_ERROR)
);
}
}
@Order : 순서를 지정, 작을 수록 우선순위@Slf4j
@RestControllerAdvice
@Order(value = Integer.MIN_VALUE)
public class ApiExceptionHandler {
@ExceptionHandler(value = ApiException.class)
public ResponseEntity<Api<Object>> apiException(ApiException apiException){
log.error("", apiException);
ErrorCodeIfs errorCodeIfs = apiException.getErrorCodeIfs();
return ResponseEntity
.status(errorCodeIfs.getHttpStatusCode())
.body(
Api.Error(errorCodeIfs, apiException.getErrorDescription())
);
}
}
@ExceptionHandler의 ApiException이 발생하면ApiException을 @ExceptionHandler가 붙어있는 레벨의 메서드인 apiException 메서드에 전달해준다