예외 처리
ExceptionController.java
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ExceptionController {
@RequestMapping("/ex")
public String main() throws Exception {
try {
throw new Exception("예외가 발생했습니다.");
} catch (Exception e) {
return "error";
}
}
}
error.jsp
<%@ page contentType="text/html;charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>error.jsp</title>
</head>
<body>
<h1>예외가 발생했습니다.</h1>
발생한 예외 : ${ex}<br>
예외 메시지 : ${ex.message}<br>
<ol>
<c:forEach items="${ex.stackTrace}" var="i">
<li>${i.toString()}</li>
</c:forEach>
</ol>
</body>
</html>
예외 처리 메소드를 하나 더 만들었는데,
코드가 중복된다.
그럴때는 @ExceptionHandler 어노테이션을 가진 메소드를 만들어
중복을 제거할 수 있다.
@Controller
public class ExceptionController {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex) { //예외를 매개변수로 줌
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception {
try {
throw new Exception("예외가 발생했습니다.");
} catch (Exception e) { //코드 중복
return "error";
}
}
@RequestMapping("/ex2")
public String main2() throws Exception {
try {
throw new Exception("예외가 발생했습니다.");
} catch (Exception e) { //코드 중복
return "error";
}
}
}
중복 제거 후 코드
@Controller
public class ExceptionController {
@ExceptionHandler(Exception.class) //별도의 예외처리를 하는 메소드 - 어노테이션 꼭 붙여줘야함
public String catcher(Exception ex) { //예외를 매개변수로 줌
return "error"; //catch블록이라고 생각하면 됨!
}
@RequestMapping("/ex")
public String main() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
@RequestMapping("/ex2")
public String main2() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
}
만약 NullPointerException이 발생하는 메소드가 있다면,
별도의 예외처리를 하는 catch블록을 하나 더 추가시킨다.
@Controller
public class ExceptionController {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex) {
return "error";
}
@ExceptionHandler(NullPointerException.class) //main2에 대한 예외 처리를 하는 메소드
public String catcher2(Exception ex) {
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
@RequestMapping("/ex2")
public String main2() throws Exception {
throw new NullPointerException("예외가 발생했습니다.");
}
}
이제 어떤 예외가 발생했는지 나오게 해보자
어떤 예외가 발생했는지 뷰에 나오게 하려면,
Model이 필요하다.
@Controller
public class ExceptionController {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex, Model model) { //메소드에서 자동으로 예외 객체 ex가 넘어가면
model.addAttribute("ex",ex); //모델로 담아서 뷰로 건네주기
return "error";
}
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ExceptionController {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex, Model model) {
model.addAttribute("ex",ex); //모델로 넘겨주기
return "error";
}
@ExceptionHandler(NullPointerException.class) //main2에 대한 예외 처리를 하는 메소드
public String catcher2(Exception ex,Model model) {
model.addAttribute("ex", ex);
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
@RequestMapping("/ex2")
public String main2() throws Exception {
throw new NullPointerException("예외가 발생했습니다.");
}
}
실행을 하면
예외 정보가 모델에 담겨 뷰에 전달된 것이다.
하나의 ExceptionHandler메소드로 두 개 이상의 예외를 처리하고 싶다면 배열을 쓰면 된다.
@Controller
public class ExceptionController {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex, Model model) {
model.addAttribute("ex",ex); //모델로 넘겨주기
return "error";
}
@ExceptionHandler({NullPointerException.class,FileNotFoundException.class}) //괄호 안에 배열을 넣어준다
public String catcher2(Exception ex,Model model) {
model.addAttribute("ex", ex);
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
@RequestMapping("/ex2")
public String main2() throws Exception {
throw new FileNotFoundException("예외가 발생했습니다.");
}
}
ExceptionHandler 메소드들은 컨트롤러에만 쓸 수 있으므로,
컨트롤러를 하나 더 만들어본다.
@Controller
public class ExceptionController2 {
@RequestMapping("/ex3")
public String main() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
@RequestMapping("/ex4")
public String main2() throws Exception {
throw new FileNotFoundException("예외가 발생했습니다.");
}
}
ExceptionHandler 메소드들을 복사해서 붙여넣어준다
@Controller
public class ExceptionController2 {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex, Model model) {
model.addAttribute("ex",ex); //모델로 넘겨주기
return "error";
}
@ExceptionHandler({NullPointerException.class,FileNotFoundException.class}) //괄호 안에 배열을 넣어준다
public String catcher2(Exception ex,Model model) {
model.addAttribute("ex", ex);
return "error";
}
@RequestMapping("/ex3")
public String main() throws Exception {
throw new Exception("예외가 발생했습니다.");
}
@RequestMapping("/ex4")
public String main2() throws Exception {
throw new FileNotFoundException("예외가 발생했습니다.");
}
}
두 개의 컨트롤러에서 코드가 중복되고 있으니,
여러 컨트롤러에서 공통으로 예외처리 할 수 있도록 바꿔본다.
@ControllerAdvice //새로운 어노테이션! 공통으로 예외처리하기 위함
public class GlobalCatcher {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex, Model model) {
model.addAttribute("ex",ex); //모델로 넘겨주기
return "error";
}
@ExceptionHandler({NullPointerException.class,FileNotFoundException.class}) //괄호 안에 배열을 넣어준다
public String catcher2(Exception ex,Model model) {
model.addAttribute("ex", ex);
return "error";
}
}
@ControllerAdvice 어노테이션을 붙이면
모든 컨트롤러에서 발생하는 예외를 다 처리하게 된다.
GlobalCatcher 클래스가 잘 처리하는 모습을 볼 수 있다.
GlobalCatcher 클래스가 전부 예외를 처리해주더라도,
같은 컨트롤러 내에 ExceptionHandler가 있다면
가까운 ExceptionHandler메소드(같은 컨트롤러 내)가 예외처리를 한다.
예외를 적용할 패키지를 지정해줄 수 있다.
@ControllerAdvice("com.fastcampus.ch2") //지정된 패키지 내에서 발생한 예외만 처리
public class GlobalCatcher {
@ExceptionHandler(Exception.class)
public String catcher(Exception ex, Model model) {
model.addAttribute("ex",ex); //모델로 넘겨주기
return "error";
}
@ExceptionHandler({NullPointerException.class,FileNotFoundException.class}) //괄호 안에 배열을 넣어준다
public String catcher2(Exception ex,Model model) {
model.addAttribute("ex", ex);
return "error";
}
}
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
'패캠 챌린지' 카테고리의 다른 글
패스트캠퍼스 챌린지 - 23일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.14 |
---|---|
패스트캠퍼스 챌린지 - 22일차 [스프링의 정석:남궁성과 끝까지 간다] (1) | 2023.03.13 |
패스트캠퍼스 챌린지 - 20일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.11 |
패스트캠퍼스 챌린지 - 19일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.10 |
패스트캠퍼스 챌린지 - 18일차 [스프링의 정석:남궁성과 끝까지 간다] (2) | 2023.03.09 |