💡 학습목표
1. Exception Handler 처리
2. @ControllerAdvice 와 @RestControllerAdvice의 차이점 이해하기
3. 사용자 정의 예외 클래스를 만들어 보기
💡 Exception Handler
스프링 MVC 의 중요한 구성 요소 중에 하나로 AOP 기반에 개념과는 약간 다른 개념 입니다.
구현하는 방법 중 하나는 @ExcetptionHandler 어노테이션을 사용하고 이 어노테이션은
예외가 발생한 메서드를 구현하고, 처리할 예외 타입을 지정합니다.
💡 @ControllerAdvice 와 @RestcontrollerAdvice
@ControllerAdvice와 @RestControllerAdvice는 모두 예외 처리를 담당하는 클래스에
붙는 어노테이션으로 스프링에서 예외 처리를 담당하는 핵심적인 요소 중 하나입니다.
그러나 두 어노테이션에 차이점은 반환 타입과 기본 응답 형태 입니다.
@ControllerAdvice 어노테이션은 View 렌더링을 위해 ModelAndView 형태로
객체를 반환하도록 기본 설정이 되어 있습니다.
즉, 요청에 대한 응답이 view 형태로 전달되며, JSP 와 같은 템플릿 엔진을 사용할 수 있습니다.
반면에 @RestControllerAdvice RESTfull 웹 서비스에서 사용하기 적합한 형태로
응답 처리가 되며 응답에 형태는 JSON, XML 형태로 반환이 됩니다.
사용자 정의 예외 클래스 만들어 보기 -1
CustomPageException.java
package com.tencoding.bank.handler.exception;
import org.springframework.http.HttpStatus;
public class CustomPageException extends RuntimeException{
private HttpStatus status;
public CustomPageException(String message, HttpStatus status) {
super(message);
this.status = status;
}
}
사용자 정의 예외 클래스 만들어 보기 - 2
CustomRestfulException.java
package com.tencoding.bank.handler.exception;
import org.springframework.http.HttpStatus;
import lombok.Getter;
// 클래스 정의
@Getter // IoC 대상이 아니다. (필요할 때 직접 new 할 예정)
public class CustomRestfulException extends RuntimeException{
private HttpStatus status;
public CustomRestfulException(String message, HttpStatus status) {
super(message);
this.status = status;
}
}
package com.tencoding.bank.handler;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.tencoding.bank.handler.exception.CustomRestfulException;
/**
* 예외 발생 시 (Json, Xml)
* 데이터를 가공해서 내려 줄 수 있다.
*
*
*/
@RestControllerAdvice // IoC 대상 + Aop 대상
public class MyRestfulExceptionHandler {
// 모든 예외가 발생했을 때
@ExceptionHandler(Exception.class)
public void exception(Exception e) {
System.out.println("=== 예외 발생 확인 ===");
System.out.println(e.getMessage());
System.out.println("----------------------");
}
// 사용자 정의 예외 클래스 활용
@ExceptionHandler(CustomRestfulException.class)
public String basicException(CustomRestfulException e) {
StringBuffer sb = new StringBuffer();
sb.append("<script>");
sb.append("alert(' "+ e.getMessage() +" ');"); // 문자열 안에 반드시 ;붙이기
sb.append("history.back();");
sb.append("</script>");
return sb.toString();
}
}
💡 사용자 정의 예외 클래스 설계
ControllerAdvice 설계
errorPage.jsp 사용
실제 적용 ControllerAdvice - Handler 처리
package com.tencoding.bank.handler;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import com.tencoding.bank.handler.exception.CustomPageException;
/**
* View 렌더링을 위해 ModelAndView
* 객체를 반환하도록 설계할 때 사용
* 예외 page를 리턴하도록 설계
*/
@ControllerAdvice // IoC의 대상
@Order(2)
public class MyPageExceptionHandler {
// 모든 예외가 발생했을 때
@ExceptionHandler(Exception.class)
public void exception(Exception e) {
System.out.println("=== 예외 발생 확인 ===");
System.out.println(e.getMessage());
System.out.println("----------------------");
}
// 사용자 정의 클래스 활용
@ExceptionHandler(CustomPageException.class)
public ModelAndView handleRunTimePageException(CustomPageException e) {
// ModelAndView 활용 방법 - 페이지 명시해야 함
ModelAndView modelAndView = new ModelAndView("errorPage");
modelAndView.addObject("statusCode", HttpStatus.NOT_FOUND.value());
modelAndView.addObject("message", e.getMessage());
return modelAndView;
}
}
errorPage.jsp
&&&&<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page isErrorPage="true" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>에러 페이지</h1>
<p>에러 코드 : ${statusCode}</p>
<p>에러 메세지 : ${message}</p>
</body>
</html>