본문 바로가기
Spring

[Spring] 예외 처리( @ExceptionHander, @ResponseStatus)

by eunoo 2022. 6. 20.

스프링에서 예외 처리하는 법을 알아보겠다.

 

[과정]

클라이언트 요청 -> 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으로 나온다.

 

댓글