스프링 예외처리 @ExceptionHandler, @ControllerAdvice 예제
스프링 예외처리를 할 때에는 @ExceptionHandler를 많이 사용한다.
controller에서 @ExceptionHandler를 통해 메소드를 정의해주면
오류 발생시 메소드를 자동으로 호출해준다.
(이때 사용하는 jsp를 오류 페이지용으로 만들어주면 된다)
ex) 네이버 오류페이지
자 이제 @ExceptionHandler에 대해서 알아보자.
컨트롤러 코드를 구성해보자.
@Controller
public class TestController {
@GetMapping("/test1")
public String test1(Model model) {
int[] array1 = {10, 20, 30};
// model.addAttribute("array1", array1[0]);
model.addAttribute("array1", array1[10]);
return "test1";
}
@ExceptionHandler(ArrayIndexOutOfBoundsException.class)//오류종류를 파라미터에 넣어준다
public String exception1() {
return "error1";
}
}
이렇게 되어있으면 array[10]이 없음으로
ArrayIndexOutOfBoundsException 에러가 발생한다.
근데 밑에 @ExceptionHandler를 추가해주고 괄호안에 일어날
오류.class 를 적어 준후
return 으로 내가 만들어준 jsp페이지(저 위에서는 error1이므로 error1.jsp)로 지정을 해준다면
이제 앞으로 배열인덱스에러 발생시에는 내가 지정해준
error1.jsp페이지로 이동하게 된다.
이런 원리를 통해 에러페이지가 깔끔하게
네이버도 원하는 오류페이지를 사용할 수 있는 것이다.
그런데 이렇게 위처럼 @ExceptionHandler를 지정해준다면 단점이있다.
클래스를 작성하다보면 여러개 많으면 몇십개의 컨트롤러를 작성 할 수도있는데
위와같은 방식을 사용하면 해당 컨트롤러에서의 에러에만
@ExceptionHandler가 반응하게 된다
즉 위와같은 방식 사용시 컨트롤러가 몇십개면 몇십개에 전부다 @ExceptionHandler를 지정해줘야한다.
(만약 컨트롤러1, 컨트롤러2가 있으면 컨트롤러1에서 아무리에러처리를해도
컨트롤러2에서는 먹히지않는다)
그건 굉장히 복잡한 방식이므로
이제 우리는 전역에러를 처리하는 방법에 대해 알아보자.
전역 예외처리는 Global Exception Handler 라고 부른다.
글로벌 예외처리는 쉽다.
@ControllerAdvice
public class GlobalExceptionHandler extends RuntimeException{
@ExceptionHandler(java.lang.NullPointerException.class)//널포인트에러발생시 실행
public String handleException() {//메소드이름은 맘대로
return "error2";
}
}
이렇게 @ControllerAdvice 를 클래스에 지정해준뒤
클래스 내용에 해당하는 메소드를 @ExceptionHandler와 함께 만들어주면 된다.
그리고 이렇게 만들어준 클래스가 속해있는 패키지를
컴포넌트스캔을 통해서 인식하게 해주기만 하면된다.
난 서ServletAppContext.java에 이렇게 한줄만 추가해줄것이다.
(이 패키지안에 위에 코드가 담긴 GlobalExceptionHandler가 들었으므로)
@ComponentScan("kr.co.softcampus.exception")
전체 코드를보면 이렇게된다.
//Spring MVC 프로젝트에 관련된 설정을 하는 클래스
@Configuration
// Controller 어노테이션이 셋팅되어 있는 클래스를 Controller로 등록한다
@EnableWebMvc
//스캔할 패키지를 지정한다
@ComponentScan("kr.co.softcampus.controller")
@ComponentScan("kr.co.softcampus.exception") //전역에러스캔을 위한 코드
public class ServletAppContext implements WebMvcConfigurer{
// Contorller의 메서드가 반환하는 jsp의 이름 앞뒤에 경로와 확장자를 붙혀주도록 설정한다.
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// TODO Auto-generated method stub
WebMvcConfigurer.super.configureViewResolvers(registry);
registry.jsp("/WEB-INF/views/", ".jsp");
}
// 정적 파일의 경로를 매핑한다
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
WebMvcConfigurer.super.addResourceHandlers(registry);
registry.addResourceHandler("/**").addResourceLocations("/resources/");
}
}
이렇게 지정만 해준다면 앞으로는
컨트롤러1의 에러도
컨트롤러2의 에러도 만약 컨트롤러100의 에러도
모두 널포인터익셉션이라면 error2.jsp를 보여주게 된다.