[Spring] Controller의 Exception 처리

업데이트:

Controller의 Exception 처리

Controll를 작성할 때 예외 상황을 고려하면 처리해야 하는 작업이 증가한다.
스프링 MVC에서는 다음 방식으로 처리할 수 있다.

  • @ExceptionHandler와 @ControllerAdvice를 이용한 처리
  • @ResponseEntity를 이용하는 예외 메시지 구성



@ControllerAdvice

@ControllerAdvice는 AOP(aspect-Oriented-Programming)를 이용하는 방식이다.

AOP는 핵심적인 로직은 아니지만 프로그램에서 필요한 ‘공통적인 관심사’는 분리하는 개념이다.
Controller를 작성할 때 메서드의 모든 예외사항을 전부 핸들링해야 한다면 중복적이고 많은 양의 코드를 작성해야 하지만 AOP 방식을 이용하면 공통적인 예외사항에 대해서는 별도로 @ControllerAdvice를 잉요해서 분리하는 방식이다.


CommonExceptionAdvice 클래스 생성

예외 처리를 목적으로 생성하는 클래스도 별도의 로직처리는 하지 않는다.

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";
	}
}


CommonExceptionAdvice 클래스에 @ControllerAdvice라는 어노테이션과 @ExceptionHandler라는 어노테이션을 사용하고 있다.

@ControllerAdvice는 해당 객체가 스프링의 컨트롤러에서 발생하는 예외를 처리하는 존재임을 명시하는 용도로 사용한다.
@ExceptionHandler는 해당 메서드가 들어가는 예외 타입을 처리한다.
@ExceptionHandler 어노테이션의 속성으로는 Exception 클래스 타입을 지정할 수 있으며, 해당 클래스는 Exception.class를 지정하였으므로 모든 예외에 대한 처리가 except()만을 이용해서 처리할 수 있다.


만일 특정한 타입의 예외를 다루고 싶다면 Exception.class 대신에 구체적인 예외의 클래스를 지정해야 한다.
JSP 화면에서도 구체적인 메시지를 보고 싶다면 Model을 이용해서 전달하는 것이 좋다.



servlet-context.xml

해당 클래스는 servlet-context.xml에서 인식하지 않기 때문에 을 이용해서 해당 패키지의 내용을 조사하도록 한다.

<context:component-scan base-package="org.zerock.exception"/>

CommonExceptionAdvice의 except()의 리턴값은 문자열이므로 JSP 파일의 경로가 된다.
JSP는 error_page.jsp이므로 /WEB-INF/views 폴더 내에 작성해야 한다.

error_page.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page session="false" import="java.util.*" %>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
	<h4><c:out value="${exception.getMessage()}"></c:out></h4>
	
	<ul>
		<c:forEach items="${esception.getStackTrace() }" var="stack">
			<li><c:out value="${stack}"></c:out></li>
		</c:forEach>
	</ul>
</body>
</html>


일부러 에러를 발생시킨 경우 화면에 예외 메세지가 출력된다.



404 에러 페이지

WAS의 구동 중 가장 흔한 에러와 관련된 HTTP 상태 코드는 ‘404’와 ‘500’ 에러 코드이다.
500 메시지는 ‘Internal Server Error’ 이므로 @ExceptionHandler를 이용해서 처리한다.
404 메시지는 잘못된 URL을 호출할 때 보여진다.

스프링 MVC의 모든 요청은 DispatcherServlet을 이용해서 처리되므로 404 에러도 같이 처리할 수 있도록 web.xml을 수정해야 한다.

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>
	<init-param>
		<param-name>throwExceptionIfNoHandlerFound</param-name>
		<param-value>true</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>


CommonExceptionAdvice클래스

	@ExceptionHandler(NoHandlerFoundException.class)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	public String handler404(NoHandlerFoundException ex) {
		return "custom404";
	}

custom404.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>

 <h1>해당 URL은 존재하지 않습니다.</h1>

</body>
</html>


브라우저에서 존재하지 않는 URL을 호출하면 custom404.jsp 페이지가 보인다.

image



관련 서적 : 코드로 배우는 스프링 웹 프로젝트

태그:

카테고리:

업데이트:

댓글남기기