이런 문제를 조금이라도 개선하기 위해 @ExceptionHandler와 @ControllerAdvice를 사용한다고 보면 이해가 쉬워진다.
@ExceptionHandler 같은 경우 @Controller, @RestController가 적용된 Bean 내에서 발생하는 예외를 잡아서 하나의 메서드에서 처리해주는 기능을 한다.
@RestController
public class MyRestController {
...
...
@ExceptionHandler(NullPointException.class)
public Object nullex(Exception e) {
System.out.println(e.getClass());
return "myService";
}
}
위 처럼 적용하기만 하면된다. @ExceptionHanlder annotation을 쓰고 인자로 캐치하고 싶은 예외 클래스를 등록해주면 된다.
주의사항/알아 둘 것
@ExceptionHandler가 하나의 클래스에 대한 것이라면, @ControllerAdvice 는 모든 @Controller 즉, 전역에서 발생하는 예외를 잡아 처리해주는 어노테이션이다.
@RestControllerAdvice
public class Myadvice {
@ExceptionHandler(CustomException.class)
public String custom() {
return "hello custom";
}
}
위 처럼 새로운 클래스 파일을 만들어서 어노테이션을 붙이면 된다.
그 다음엔 @ExceptionHandler로 처리하고 싶은 예외를 잡아 처리한다.
별도의 속성값이 없어 사용하면 모든 패키지 전역에 있는 컨트롤러를 담당하게 된다.
@RestControllerAdvice && @ControllerAdvice가 존재하는데 @RestControllerAdvice 어노테이션을 확인해보면
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
//...
}
@ControllerAdvice과 동일한 역할
즉, 예외를 잡아 핸들링 할 수 있도록 기능을 수행하면서 @ResponseBody를 통해 객체를 리턴할 수 도있다는 뜻이다.
ViewResolver를 통해서 예외 처리 페이지로 리다이렉트 시키면 @ControllerAdvice만 써도 되고, API 서버에서 에러 응답으로 객체를 리턴해야한다면 @ResponseBody 어노테이션이 추가된 @RestControllerAdvice 적용하면 되는 것이다