
@ControllerAdvice
@ControllerAdvice는 전역적으로 컨트롤러에서 발생하는 예외를 처리하거나 공통 로직을 적용하기 위해 사용되는 어노테이션이다. (AOP를 기반으로 한다)
기본적으로 속성을 지정하지 않으면 애플리케이션 모든 컨트롤러에 적용된다.
1) basePackages
- 특정 패키지 및 그 하위 패키지인 컨트롤러에만 @ControllerAdvice를 적용.
- 여러 패키지 지정 가능
2) basePackageClasses
- 패키지 이름을 문자열로 지정하는 대신, 특정 클래스의 패키지를 참조.
3) assignableTypes
- 특정 클래스 또는 그 하위 클래스에만 적용
4) annotations
- 특정 어노테이션이 붙은 컨트롤러에만 적용.
- Spring 5.3 이상에서 HTTP 메서드별 어노테이션(예: @PostMapping, @DeleteMapping도 사용 가능)
5) value
- basePackages와 동일한 역할을 하며, 패키지 이름을 지정
- 예: @ControllerAdvice("okestro.third.domain.openstack.ctr")
Order에 Global 부분이 가장 늦도록 설정 해주어야 한다.Global Exception
@Slf4j
@Order(Ordered.LOWEST_PRECEDENCE)
@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler {
/**
* 나머지 예외 발생
*/
@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);
}
}
Controller Exception
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice(basePackageClasses = LoadbalancerController.class)
@RequiredArgsConstructor
public class LbExceptionHandler {
@ExceptionHandler(value = {LoadBalancerCertDeleteException.class})
protected ResponseEntity<ErrorResponse> deleteCertException(LoadBalancerCertDeleteException e) {
log.error("==== LoadBalancer 인증서 삭제 실패: 이미 바인딩된 인증서입니다. 로드밸런서명: {}", e.getVServerName());
String message = String.format("%s 로드밸런서에 바인딩되어 있는 인증서입니다. 해제 후 삭제 해주세요.", e.getVServerName());
return ResponseEntity
.badRequest()
.body(
ErrorResponse.of(e.getErrorCode().getErrorCode(), message)
);
}
}
Controller의 어노테이션으로도 구분할 수 있다.package okestro.third.domain.openstack.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
@ControllerAdvice(basePackages = "okestro.third.domain.openstack.ctr", annotations = PostMapping.class)
public class PostExceptionHandler {
@ExceptionHandler(OsNetworkCreateException.class)
public ResponseEntity<String> handleOsNetworkCreateException(OsNetworkCreateException ex) {
return new ResponseEntity<>("POST request failed: " + ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}