Spring

34. 예외처리/실습 - 패스트캠퍼스 백엔드 부트캠프 3기

gkss2tpt 2025. 2. 17. 11:36

1. 예외처리

  • ExceptionController
@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메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex){
        return "error";
    }

    @RequestMapping("/ex")
    public String main() throws Exception{
        throw new Exception("예외가 발생했습니다.");
    }

    @RequestMapping("/ex2")
    public String main2() throws Exception{
        throw new Exception("예외가 발생했습니다.");
    }
}
  • 추가 가능
@Controller
public class ExceptionController {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex){
        return "error";
    }
    // 추가 가능
    @ExceptionHandler(NullPointerException.class)
    public String catcher2(NullPointerException ex){
        return "error";
    }

    @RequestMapping("/ex")
    public String main() throws Exception{
        throw new Exception("예외가 발생했습니다.");
    }

    @RequestMapping("/ex2")
    public String main2() throws Exception{
        throw new NullPointerException("예외가 발생했습니다.");
    }
}

  • 여러개의 예외 선언
@Controller
public class ExceptionController {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
//    @ExceptionHandler(Exception.class)
//    public String catcher(Exception ex, Model m){
//        m.addAttribute("ex", ex);
//        return "error";
//    }
    // 추가 가능
    @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
    public String catcher2(NullPointerException ex, Model m){
        m.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("예외가 발생했습니다.");
    }
    @RequestMapping("/ex3")
    public String main3() throws Exception{
        throw new FileNotFoundException("예외가 발생했습니다.");
    }
}

  • 제대로 안나오는 이유...
    @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
    public String catcher2(Exception ex, Model m){
        m.addAttribute("ex", ex);
        return "error";
    }
  • 매개변수를 NullPointerException만 잡아줘서 안되었다.

  • 다시 잘 나오는 모습
@Controller
public class ExceptionController2 {
    @RequestMapping("/ex4")
    public String main() throws Exception{
        throw new Exception("예외가 발생했습니다.");
    }

    @RequestMapping("/ex5")
    public String main2() throws Exception{
        throw new NullPointerException("예외가 발생했습니다.");
    }
    @RequestMapping("/ex6")
    public String main3() throws Exception{
        throw new FileNotFoundException("예외가 발생했습니다.");
    }
}
  • 예외 처리 메서드가 없는 새로운 클래스 ExceptionController2

  • 예외처리가 안된모습
  • 컨트롤러 내부에서만 @ExceptionHandler의 메서드가 실행되기 때문
  • @ControllerAdvice
@ControllerAdvice
public class GlobalCatcher {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex, Model m){
        m.addAttribute("ex", ex);
        return "error";
    }
    // 추가 가능
    @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
    public String catcher2(Exception ex, Model m){
        m.addAttribute("ex", ex);
        return "error";
    }
}
  • 모든 컨트롤러에서 발생하는 예외를 처리하는 클래스

  • 컨트롤러 내부에 @ExceptionHandler가 없어도 @ControllerAdvice에서 잘 처리 되는 모습 
  • @ControllerAdvice와 @ExceptionHandler가 둘다 있다면? 가까운 쪽이 처리한다.
public class GlobalCatcher {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex, Model m){
        System.out.println("catcher() in GlobalController");
        m.addAttribute("ex", ex);
        return "error";
    }
    // 추가 가능
    @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
    public String catcher2(Exception ex, Model m){
        System.out.println("catcher() in GlobalController");
        m.addAttribute("ex", ex);
        return "error";
    }
}
@Controller
public class ExceptionController {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex, Model m){
        System.out.println("catcher() in ExceptionController");
        m.addAttribute("ex", ex);
        return "error";
    }
    // 추가 가능
    @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
    public String catcher2(Exception ex, Model m){
        System.out.println("catcher() in ExceptionController");
        m.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("예외가 발생했습니다.");
    }
    @RequestMapping("/ex3")
    public String main3() throws Exception{
        throw new FileNotFoundException("예외가 발생했습니다.");
    }
}

  • 패키지 지정
//@ControllerAdvice("com.fastcampus.ch2")   // 지정된 패키지에서 발생한 예외만 처리
@ControllerAdvice   // 모든 패키지에 적용
public class GlobalCatcher {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex, Model m){
        System.out.println("catcher() in GlobalController");
        m.addAttribute("ex", ex);
        return "error";
    }
    // 추가 가능
    @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
    public String catcher2(Exception ex, Model m){
        System.out.println("catcher() in GlobalController");
        m.addAttribute("ex", ex);
        return "error";
    }
}
  • @ExceptionHandler의Model객체와 @RequestMapping의 Model 객체는 다르다. 
@Controller
public class ExceptionController {
    // 별도의 예외처리 메서드
    // 컨트롤러 내부에서 예외가 발생시 @ExceptionHandler메서드 실행
    @ExceptionHandler(Exception.class)
    public String catcher(Exception ex, Model m){
        System.out.println("m="+m);
        m.addAttribute("ex", ex);
        return "error";
    }
    @RequestMapping("/ex")
    public String main(Model m) throws Exception{
        m.addAttribute("msg", "message from ExceptionController.main()");
        throw new Exception("예외가 발생했습니다.");
    }
}

  • main메서드에서 저장된 Model객체의 값이 catcher에서 나오지 않는모습