일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 자바
- 트랜잭션
- 인터셉터
- proxy pattern
- git
- OOP
- SQL
- java
- network
- 객체지향프로그래밍
- Filter
- exception
- aop
- mybatis
- 스프링
- 스프링 시큐리티
- MYSQL
- http
- RestControllerAdvice
- Spring Security
- spring boot
- Redis
- 관점지향프로그래밍
- response
- Spring
- 디자인패턴
- Interceptor
- 스프링부트
- request
- aspect
- Today
- Total
장쫄깃 기술블로그
[Spring Boot] @RestControllerAdvice 란 본문
들어가며
자사 서드파티 API를 개발하는 업무를 담당했을 때, 처음에는 모든 예외처리를 try-catch로 처리하였다. 그렇다 보니 불필요한 중복 코드들이 많아지고 가독성도 떨어졌다. 또, 코드가 점점 복잡해져 생산성도 떨어졌다. 확실한 건 중복되는 코드들이 너무 많았다. 이러한 문제를 해결하기 위해 고민하고 찾아본 결과 @ControllerAdvice, @RestControllerAdvice를 발견했다.
@ControllerAdvice 란
/**
* Specialization of {@link Component @Component} for classes that declare
* {@link ExceptionHandler @ExceptionHandler}, {@link InitBinder @InitBinder}, or
* {@link ModelAttribute @ModelAttribute} methods to be shared across
* multiple {@code @Controller} classes.
*
* <p>Classes annotated with {@code @ControllerAdvice} can be declared explicitly
* as Spring beans or auto-detected via classpath scanning. All such beans are
* sorted based on {@link org.springframework.core.Ordered Ordered} semantics or
* {@link org.springframework.core.annotation.Order @Order} /
* {@link javax.annotation.Priority @Priority} declarations, with {@code Ordered}
* semantics taking precedence over {@code @Order} / {@code @Priority} declarations.
* {@code @ControllerAdvice} beans are then applied in that order at runtime.
* Note, however, that {@code @ControllerAdvice} beans that implement
* {@link org.springframework.core.PriorityOrdered PriorityOrdered} are <em>not</em>
* given priority over {@code @ControllerAdvice} beans that implement {@code Ordered}.
* In addition, {@code Ordered} is not honored for scoped {@code @ControllerAdvice}
* beans — for example if such a bean has been configured as a request-scoped
* or session-scoped bean. For handling exceptions, an {@code @ExceptionHandler}
* will be picked on the first advice with a matching exception handler method. For
* model attributes and data binding initialization, {@code @ModelAttribute} and
* {@code @InitBinder} methods will follow {@code @ControllerAdvice} order.
*
* <p>Note: For {@code @ExceptionHandler} methods, a root exception match will be
* preferred to just matching a cause of the current exception, among the handler
* methods of a particular advice bean. However, a cause match on a higher-priority
* advice will still be preferred over any match (whether root or cause level)
* on a lower-priority advice bean. As a consequence, please declare your primary
* root exception mappings on a prioritized advice bean with a corresponding order.
*
* <p>By default, the methods in an {@code @ControllerAdvice} apply globally to
* all controllers. Use selectors such as {@link #annotations},
* {@link #basePackageClasses}, and {@link #basePackages} (or its alias
* {@link #value}) to define a more narrow subset of targeted controllers.
* If multiple selectors are declared, boolean {@code OR} logic is applied, meaning
* selected controllers should match at least one selector. Note that selector checks
* are performed at runtime, so adding many selectors may negatively impact
* performance and add complexity.
*
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Sam Brannen
* @since 3.2
* @see org.springframework.stereotype.Controller
* @see RestControllerAdvice
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@ControllerAdvice는 @ExceptionHandler, @ModelAttribute, @InitBinder가 적용된 메소드들에 AOP를 적용하여 Controller단에 적용하기 위해 고안된 어노테이션이다. 클래스에 선언되며, 모든 @Controller에 대한 전역적으로 발생할 수 있는 예외를 잡아서 처리할 수 있다.
@RestControllerAdvice 란
/**
* A convenience annotation that is itself annotated with
* {@link ControllerAdvice @ControllerAdvice}
* and {@link ResponseBody @ResponseBody}.
*
* <p>Types that carry this annotation are treated as controller advice where
* {@link ExceptionHandler @ExceptionHandler} methods assume
* {@link ResponseBody @ResponseBody} semantics by default.
*
* <p><b>NOTE:</b> {@code @RestControllerAdvice} is processed if an appropriate
* {@code HandlerMapping}-{@code HandlerAdapter} pair is configured such as the
* {@code RequestMappingHandlerMapping}-{@code RequestMappingHandlerAdapter} pair
* which are the default in the MVC Java config and the MVC namespace.
*
* @author Rossen Stoyanchev
* @author Sam Brannen
* @since 4.3
* @see RestController
* @see ControllerAdvice
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
@RestControllerAdvice는 @ControllerAdvice와 @ResponseBody를 합친 어노테이션이다. @ControllerAdvice의 역할을 수행하고, @ResponseBody를 통해 객체를 리턴할 수 있다.
따라서 단순히 예외 처리를 하고 싶다면 @ControllerAdvice를, 응답으로 객체를 리턴해야 한다면 @RestControllerAdvice를 적용하면 된다.
위 두 어노테이션 모두 적용 범위를 클래스나 패키지 단위로 제한할 수 있으며, 아래와 같이 사용하면 된다.
@RestControllerAdvice(basePackageClasses = TestExceptionController.class)
public class ApiExceptionAdvice {
// ...
}
@RestControllerAdvice(basePackages = "com.jdh.restControllerAdvice.controller")
public class ApiExceptionAdvice {
// ...
}
@ExceptionHandler 란
@ExceptionHandler 어노테이션을 메소드에 선언하고 특정 예외 클래스를 지정해주면 해당 예외가 발생했을 때 메소드에 정의한 로직으로 처리할 수 있다. @ControllerAdvice 또는 @RestControllerAdvice에 정의된 메소드가 아닌 일반 컨트롤러 단에 존재하는 메소드에 선언할 경우, 해당 Controller에만 적용된다.
@Service 등의 빈에서는 적용되지 않는다.
정리하며
이번 게시글에선 @ControllerAdvice, @RestControllerAdvice에 대해 알아보았다. 다음 게시글에선 해당 어노테이션을 사용하여 예외 처리하는 방법에 대해서 알아보겠다.
참고
'Spring Framework > Spring Boot' 카테고리의 다른 글
[Spring Boot] 개발-운영 환경 resource 나누기 (Gradle) (2) | 2022.10.30 |
---|---|
[Spring Boot] @RestControllerAdvice 를 사용한 예외 처리 (2) | 2022.09.25 |
[Spring Boot] MyBatis란? (0) | 2022.07.03 |
[Spring Boot] Meta Annotation (@Target, @Retention) (0) | 2022.06.26 |
[Spring Boot] 등록되는 빈의 순서를 정하자 (@DependsOn) (0) | 2022.06.26 |