스프링에서 예외 처리하는 법을 알아보겠다.
[과정]
클라이언트 요청 -> DispatcherServlet -> Controller (! 예외발생 !) -> DispatcherServlet -> handlerExceptionResolvers
handlerExceptionResolver 에선 다음의 우선순위로 예외를 처리한다.
① ExceptionHandlerExceptionResolver
② ResponseStatusExceptionResolver
③ DefaultHandlerExceptionResolver
1. @ExceptionHandler
package com.hyoding.ch1
@Controller
public class ExceptionController {
// @ExceptionHandler(Exception.class)
// public String catcher1() {
// System.out.println("==============catcher1 호출============");
// return "error";
// }
@ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
public String catcher2() {
System.out.println("==============catcher2 호출============");
return "error";
}
@RequestMapping("/ex")
public void main() throws Exception{
throw new Exception("Exception 예외 발생");
}
@RequestMapping("/ex2")
public void main2() throws Exception{
throw new NullPointerException("NullPointerException 예외 발생");
}
}
@ExceptionHandler(Exception.class) 를 메서드에 붙여주면 Exception 예외가 발생했을 때 예외 처리를 해준다.
catcher2 처럼 {} 를 넣어서 여러개의 예외를 처리할 수도 있다.
두번째로 @ControllerAdvice를 사용해서 공통적인 예외를 처리할 수도 있다.
package com.hyoding.ch1
//@ControllerAdvice//모든 패키지에서 발생한 예외 처리
@ControllerAdvice("com.hyoding.ch1")//지정된 패키지에서 발생한 예외 처리
public class GlobalCatcher {
@ExceptionHandler(Exception.class)
public String catcher3() {
System.out.println("===========Global Catcher3===========");
return "error";
}
@ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
public String catcher4() {
System.out.println("==========Global Catcher4=============");
return "error";
}
}
com.hyoding.ch1 패키지에서 발생한 예외만 처리한다.
그럼 위 코드의 main, mian2에서 발생한 예외는 어디서 처리할까? 각각 catcher3, catcher2에서 처리한다!
더 가까이 있는 @ExceptionHandler를 실행하고, GlobalCatcher클래스의 @ExceptionHandler를 실행한다는 걸 알 수 있다.
2. @ResponseStatus
statuscode를 바꿔주는 역할을 한다.
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String catcher3() {
System.out.println("===========Global Catcher3===========");
return "error";
}
BAD_REQUEST 는 400
INTERAL_SERVER_ERROR 는 500 으로 바꿔준다.
3. 스프링에서 예외처리
1. try-catch 문 사용
2. 컨트롤러에 @ExceptionHandler로 메서드 처리
3. @ControllerAdvice 클래스의 @ExceptionHandler로 메서드 처리
4. 예외 종류별로 뷰 지정하기
5. statuscode별로 뷰 지정하기
2,3번은 위에서 알아봤고 4번 예외 종류별로 뷰 지정을 해보자.
servlet-content.xml 에 다음 코드 추가
<beans:bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<beans:property name="defaultErrorView" value="error"/>
<beans:property name="exceptionMappings">
<beans:props>
<beans:prop key="com.hyoding.ch1.MyException">error400</beans:prop>
</beans:props> <!--MyException 에러를 error400.jsp로 처리 -->
</beans:property>
<beans:property name="statusCodes">
<beans:props>
<beans:prop key="error400">404</beans:prop> <!--statusCode는 404로 처리 -->
</beans:props>
</beans:property>
</beans:bean>
MyException을 작성했다치고,,, MyException이 발생하면 views/error400.jsp 이 나오도록 설정해주었다.
@ControllerAdvice 클래스에서 @ExceptionHandler로 처리한 것이 먼저 실행되니 주의하자.
그다음으로는 MyException에 @ResponseStatus로 응답 상태 코드를 바꿔준 것이 지정되니 주의하자.
5번 응답 상태 코드별로 뷰 지정하기는 WEB-INF/web.xml 에 다음 코드 추가해주자.
<!-- 에러 페이지 처리 -->
<error-page>
<error-code>400</error-code>
<location>/error400.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error500.jsp</location>
</error-page>
error400.jsp 와 error500.jsp를 webapp에 추가해줘야한다.
응답 상태 코드가 400이면 error400.jsp로 처리한다.
error.jsp 는 다음과 같이 작성했다.
<%@ page contentType="text/html;charset=utf-8" isErrorPage="true"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>error.jsp</title>
</head>
<body>
<h1>예외가 발생했습니다.</h1>
발생한 예외 : ${pageContext.exception}<br>
예외 메시지 : ${pageContext.exception.message}<br>
<ol>
<c:forEach items="${pageContext.exception.stackTrace}" var="i">
<li>${i.toString()}</li>
</c:forEach>
</ol>
</body>
</html>
isErrorPage = "true" 이면 응답 상태 코드가 디폴트로 500이다.
@ResponseStatus를 이용해서 응답 상태 코드를 바꾸고 싶다면 isErrorPage = "false"로 바꿔줘야한다.
true이면 500으로 나온다.
'Spring' 카테고리의 다른 글
[Spring] 요청 URL 경로 출력하기(feat. Filter) (0) | 2022.07.14 |
---|---|
[Spring] DispatcherServlet 구현하기 (0) | 2022.07.05 |
[Spring] HttpServletResquest, HttpServletResponse (0) | 2022.07.03 |
[Spring] WebDataBinder로 데이터 타입 변환, 검증하기 (0) | 2022.06.22 |
[Spring]spring 개발환경 설정하기(windows) (0) | 2022.06.07 |
댓글