JoJun's
Jun's Devlog
JoJun's
전체 방문자
오늘
어제
  • 분류 전체보기 (51)
    • Java (16)
      • SpringBoot (12)
      • Java (4)
    • Linux (11)
      • CentOS (4)
      • 명령어(CentOS) (5)
      • Docker (2)
    • DataBase (15)
      • 튜닝 기법 (1)
      • MSSQL (7)
      • SQLD,SQLP (6)
    • 알고리즘 (4)
      • 정렬 (1)
      • 해시 (1)
      • 완전탐색 (1)
      • 탐욕법 (1)
    • 인프라 (3)
    • Web (2)
    • 개인공간 (0)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • 파일그룹
  • log4j2
  • MSSQL
  • Dockerfile
  • cors
  • 알고리즘
  • docker
  • springboot
  • @Component
  • Java

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
JoJun's

Jun's Devlog

[SpringBoot] Exception Handler 예외를 통합관리 하자.!!!
Java/SpringBoot

[SpringBoot] Exception Handler 예외를 통합관리 하자.!!!

2022. 4. 15. 10:53
728x90
반응형

요즘 YOPLE 서비스를 개발하면서 Exception을 핸들링해야 하는 일이 생겼다.

스프링 구조상  컨트롤러-서비스-JDBC lib를 통해 API가 처리되면서 Controller단에서 Throw 되는 Exception을 핸들링하고자 한다.

 

기존 예외 처리 방식은 trty-catch를 각 메소드별로 설정해주어 처리했다. 각 Exception별로 처리하는 중복 코드가 try-catch별로 생성되어 코드가 방대해지고 복잡해졌다..... 

그래서 찾아보니 @ControllerAdvice와 @ExceptionHandler 두 어노테이션으로 Exception을 전역으로 처리할 수 있다고 한다.!!!

@ExceptionHandler

SpringFramwork Docs에서 @ExceptionHandler는 아래와 같이 설명하고 있다.


"Annotation for handling exceptions in specific handler classes and/or handler methods."

 

 특정 클래스의 메서드에서 Exception핸들링을 하기 위한 어노테이션이다.    @Controller, @RestContorller가 아닌 @Service, @Repository의 Bean에서는 사용할 수 없다.

실제 사용은 아래와 같다.

@Controller
public class ExceptionController {

    // ...

    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity<Object> handle(RuntimeException ex) {
        // ...
    }
}

ExceptionController에서 발생하는 RuntimeException을 handle() 메서드로 공통적으로 핸들링이 가능하다.!!

주의할 점은. 해당 메서드는 ExceptionController에서 발생하는 RuntimeException만 핸들링이 가능하다는 것이다.

그렇다면 이 메서드를 모든 컨트롤러에 작성을 해주어야 하는데...... 이러한 문제를 @ControllerAdvice로 해결이 가능하다.

@ControllerAdvice

 

ControllerAdvice (Spring Framework 5.3.19 API)

Specialization of @Component for classes that declare @ExceptionHandler, @InitBinder, or @ModelAttribute methods to be shared across multiple @Controller classes. Classes annotated with @ControllerAdvice can be declared explicitly as Spring beans or auto-d

docs.spring.io

@ControllerAdvice는 모든 컨트롤러(@Controller, @RestController)에 @ControllerAdvice에 정의된 메서드들을 매핑시켜준다.

@ControllerAdvice
public class GlobalExceptionHandler  {
    private final Logger logger = LogManager.getLogger(GlobalExceptionHandler.class);

    // 사용자 정의 예외
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<ResponseJsonObject> handleRuntimeException(RuntimeException ex) {
        ......
        return new ResponseEntity<>(ResponseJsonObject.withStatusCode(ApiStatusCode.SYSTEM_ERROR), HttpStatus.BAD_REQUEST);
    }

    // 로그인시 존재하지 않는 유저인 경우 발생하는 Exception
    @ExceptionHandler(UsernameNotFoundException.class)
    public ResponseEntity<ResponseJsonObject> handleUsernameNotFoundException(UsernameNotFoundException ex) {
        ......
        return new ResponseEntity<>(ResponseJsonObject.withStatusCode(ApiStatusCode.USER_NOT_FOUND), HttpStatus.OK);
    }

    // @RequestBody, @RequestHeader 유효성 실패.
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<ResponseJsonObject> handleConstraintViolationException(ConstraintViolationException ex) {
        ......
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    // @RequestBody 유효성 실패.
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers,
                                                                  HttpStatus status, WebRequest request) {
	.....
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    // 사용자 정의 예외
    @ExceptionHandler(YOPLEServiceException.class)
    public ResponseEntity<ResponseJsonObject> handleYOPLEServiceException(YOPLEServiceException ex) {
       ......
        return new ResponseEntity<>(ex.getResponseJsonObject(), HttpStatus.OK);
    }
}

GlobalExceptionHandler.class에 정의된 모든 메서드는 모든 Controller에 매핑되고, 각 메소드는 각 컨트롤러에서 발생하는 Exception을 핸들링하는 @ExceptionHandler로 예외를 관리한다.

 

** 만약 AOP를 사용하여 컨트롤러 메서드의 JoinPoint를 잡아 후 처리를 해준다면.  JoinPoint에서 Exception이 발생하면 AOP에서도 Exception을 Throw 해주어야 Handler에서 캐치할 수 있다. (spring life cycle참고.!)

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Java > SpringBoot' 카테고리의 다른 글

[Spring Boot] Filter  (0) 2022.06.08
[SpringBoot] JPA Entity Listener 엔티티 이벤트 리스너  (2) 2022.04.26
[SpringBoot] Log4j2 기본 사용법  (0) 2022.03.07
[SpringBoot] SOP, CORS 이야기  (0) 2022.02.03
[SpringBoot] Security 인증 절차 시 DB Access 여러번 일어나는 이슈.  (0) 2022.01.12
    'Java/SpringBoot' 카테고리의 다른 글
    • [Spring Boot] Filter
    • [SpringBoot] JPA Entity Listener 엔티티 이벤트 리스너
    • [SpringBoot] Log4j2 기본 사용법
    • [SpringBoot] SOP, CORS 이야기
    JoJun's
    JoJun's
    JoJun's의 기술블로그

    티스토리툴바