(Spring)예외처리 - Exception Handler & ControllerAdvice

DevSeoRex·2022년 6월 9일
1

Spring

목록 보기
2/3

이제 스프링 DI & AOP 에 대한 개념과 실습이 들어가있는 3강까지 갈 날이 얼마 안남았다. 오늘은 예외처리에 대한 실습과 이론 강의를 들었다.

@Controller
public class ExceptionController {
	
	// ExceptionHandler로 예외 잡기
	
	@ExceptionHandler(Exception.class)
	public String handler1(Exception e,Model m) {
		m.addAttribute("e", e);
		return "error";
	}
	
	// ExceptionHandler로 예외 잡기
	
	@ExceptionHandler(NullPointerException.class)
	public String handler2(Exception e,Model m) {
		m.addAttribute("e", e);
		return "error";
	}
	
	
	// 예외(Exception 발생 시키기)
	@RequestMapping("/ex1")
	public String main() throws Exception{
		throw new Exception("예외 발생!");
	}
	
	// 예외(Exception 발생 시키기)
	@RequestMapping("/ex2")
	public String main2() throws NullPointerException{
		throw new NullPointerException("예외 발생!");
	}
}

가장 처음에 작성한 ExceptionController1 이다. 이 클래스 에서는, Mapping한 주소 "/ex1" , "/ex2" 로 접근하게 되면 각각 Exception 과 NullpointerException을 발생시킨다.

Model에 Exception 객체를 담아 보내서, error.jsp 에서 예외의 내용을 출력해주게 하였다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ERROR</title>
</head>
<body>
	${e} <br>
	${e.message} <br>
	<ol>
	<c:forEach var="i" items="${e.stackTrace}">
		<li>${i.toString()}</li>
	</c:forEach>
	</ol>
</body>
</html>

아까 Model에 담아보낸 "e" 속성을 이용해서, 예외의 내용와 메세지 등을 화면에 찍어줄 수 있도록 JSTL을 통해 출력해주었다.

GlobalCatcher 클래스를 작성하였는데, 이 클래스는 패키지 내의 모든 예외를 잡아주는 클래스이다.

@ControllerAdvice("com.test1.rexdev1") //해당 패키지의 예외만 잡음
public class GlobalCatcher {
	
	@ExceptionHandler(Exception.class)
	public String handler1() {
		return "error2";
	}
	

	@ExceptionHandler(NullPointerException.class)
	public String handler2() {
		return "error2";
	}
	
}

@ControllerAdvice() 에너테이션 괄호 안에 아무것도 쓰지 않게 되면, 프로젝트 전체의 예외를 잡아주고(해당 하는 예외만), 에너테이션 괄호 안에 패키지 단위로 "com.test1.rexdev1" 패키지 이름을 적어주게 되면 해당 패키지의 예외만 처리해준다.

예외처리를 해주는 주체를 결정하는 방법은, 같은 클래스 내에 예외를 처리해 줄 수 있는 @ExceptionHandler가 있을경우, 예외를 해당 클래스 내의 @ExceptionHandler가 처리해주고, 예외를 클래스 내에서 처리해줄 핸들러가 없을 경우에는 @ControllerAdvice 에너테이션이 붙어있는 GlobalCathcer 클래스에서 예외를 처리해준다.

@ResponseStatus(HttpStatus.BAD_REQUEST)
//@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//@ResponseStatus(HttpStatus.NOT_FOUND)
//@ResponseStatus(HttpStatus.BAD_GATEWAY)
class MyException extends RuntimeException{
	
	MyException(String msg){
		super(msg);
	}
	
	MyException(){
		this("");
	}
}

@Controller
public class ExceptionController2 {
	
//	// ExceptionHandler로 예외 잡기
//	@ExceptionHandler(Exception.class)
//	public String handler1(Exception e,Model m) {
//		m.addAttribute("e", e);
//		return "error";
//	}
	
	// ExceptionHandler로 예외 잡기
	@ExceptionHandler(NullPointerException.class)
	public String handler2(Exception e,Model m) {
		m.addAttribute("e", e);
		return "error";
	}
	
	
	// 예외(Exception 발생 시키기)
	@RequestMapping("/ex3")
	public String main() throws Exception{
		throw new MyException("예외 발생!");
	}
	
	// 예외(Exception 발생 시키기)
	@RequestMapping("/ex4")
	public String main2() throws NullPointerException{
		throw new NullPointerException("예외 발생!");
	}
}

마지막은 사용자 정의 예외이다. 사용자 정의 예외는 예외처리를 위해 만들어진 클래스를 제외하고 사용자가 직접 만든 예외를 뜻한다.

MyException이라는 예외 클래스를 만들어주고 RuntimeException을 상속받았다. "/ex4"로 Mapping 된 예외는 처리해줄 Exception Handler가 있지만 "/ex3"로 Mapping된 사용자 정의 예외에 대해서는 처리해줄 핸들러가 없는 상태다.

일단 오류코드를 원하는 오류코드로 바꿔서 응답 받기 위해서 @ResponseStatus(HttpStastus."메소드") 에너테이션을 이용해서 "400(BAD_REQUEST),404(NOT_FOUND),500(INTERNAL_SERVER_ERROR),502(BAD_GATEWAY)" 를 각각 돌아가며 응답받게 하였다.

여기서 View가 정해지지 않은 상태로 예외가 발생하게 되면 기본 오류페이지가 사용자에게 보여지므로, web.xml 에서 error 페이지를 설정하고 , webapp 최상단에 에러 페이지 4개를 만들어 주었다.

<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>
	<error-page>
		<error-code>404</error-code>
		<location>/error404.jsp</location>
	</error-page>
	<error-page>
		<error-code>502</error-code>
		<location>/error502.jsp</location>
	</error-page>

error-page 태그로 내용을 감싸주고,
error-code 태그의 내용은 숫자로 된 에러코드를 넣어주고, location 태그의 내용은 파일의 이름을 넣어주면 된다.

ResponseStatus 에너테이션이 없을 경우,
MyException 예외가 발생하면 이런 화면이 출력된다.

ResponseStatus 에너테이션을 이용해서 에러 코드를 400(BAD_REQUEST)로 변경해서 응답받고 에러페이지가 어떻게 나오는지 확인해 보면 다음과 같이 출력된다.

미리 만들어둔 예외처리 페이지가 나오는 것을 확인 할 수 있다. 에러코드가 표시 되도록 페이지를 간단히 작성하였으니, 400번이 써있는 페이지가 출력되었다는 것은, 에러가 500번 - > 400번이 되었다는 이야기가 된다.

0개의 댓글