Spring MVC의 컨트롤러에서 예외상황을 고려해 코드를 작성하게 되면 작업량이 매우 많아지고 중복적이 된다.
Spring에서 Exception을 처리하는 방식은 다음과 같다.
@ControllerAdvice는 AOP를 이용하여 공통적인 예외사항에 대해서 별도로 분리하여 처리하는 방식이다.
package org.zerock.exception;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import lombok.extern.log4j.Log4j;
@ControllerAdvice
@Log4j
public class CommonExceptionAdvice {
@ExceptionHandler(Exception.class)
public String except(Exception ex, Model model) {
log.error("Exception........" + ex.getMessage());
model.addAttribute("exception", ex);
log.error(model);
return "error_page";
}
}
위와 같이 클래스 선언할때 붙여주면 이 클래스는 Controller에서 발생한 예외를 처리하는 클래스가 된다.
내부에 선언된 메서드에는 @ExceptionHandler
가 붙어있는데 속성값으로 예외타입을 지정하여 해당 예외가 발생했을 때 수행될 메서드가 된다.
예제에서는 Exception.class를 사용하였으므로 모든 예외상황을 except메서드가 처리할 것이다.
위 컨트롤러어드바이스 객체는 org.zerock.exception 패키지에 속하도록 생성하였는데 이를 servlet-context.xml에서 인식할 수 없으므로 component-scan태그를 이용해 등록한다.
<context:component-scan base-package="org.zerock.exception"></context:component-scan>
WAS를 구동하면서 가장 흔하게 마주치는 것은 404 에러와 500 에러일 것이다.
HTTP의 Status code에서 400번대는 클라이언트측의 잘못된 요청때문에 일어난다. (ex.없는 경로의 자원을 요청한다)
500번대는 서버내부의 에러
기존에 JSP/Servelt으로 이용한 개발에서는 별도의 에러페이지를 web.xml을 이용하여 지정할 수 있었다.
보통 에러메세지는 엔드유저들에게 불친절하고 불필요한 정보들이 많다. 그렇기에 사용자에게 너가 ~~~를 잘못했고 ~~~를 하지말고 ~~~해야해!
라고 알려주기 보단 그냥 여긴 안되용!
하고 간단히 알려주는 것이 좋을 것이다.
즉 에러페이지를 custom하여 보여줄 수 있음.
Spring MVC의 모든 요청은 DispatcherServlet을 이용하여 처리되므로 404 에러도 같이 처리하게 web.xml을 수정한다.
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
기존에 저렇게 되어있는 부분에 <init-param\>
태그를 추가한다.
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
테스트)
위에 작성한 Advice클래스에 아래 메서드를 추가
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handle404(NoHandlerFoundException ex) {
return "custom404";
}
이후 주소창에 없는 URL을 호출해봄으로써 테스트( 미리 custom404.jsp는 만들어둬야합니다.)