예외처리를 잘해주어야 비정상적인 종료를 막을수있고 , 좋은 프로그램을 만들수있다.
스프링에서는 예외처리를 해주는 방법이 여러가지있다. 각 상황에 맞게 스프링에서 제공하는 예외처리 방법을 잘사용해야한다.
🔰@ExceptionHandler로 예외처리 하는 방법
@Controller
public class ExceptionController {
@ExceptionHandler(NullPointerException.class) ////처리할 예외 종류를 작성하고 @ExceptionHandler 에노테이션을 붙여준다.
public String catcher2(Exception ex , Model m , HttepServelRequest requset) {
// request.setAttribute("ex" , ex);
m.addAttribute("ex",ex);
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception{
throw new Exception("예외가 발생했습니다.");
}
URL에 localhost/ch2/ex 치면 해당 컨트롤러에 매핑되있는 main메서드가 실행되면서 -> 예외가발생한다.
해당 main 메서드에서 try-catch블럭을 사용해서 예외 처리를 해줘도 되지만 , 해당 컨트롤러에 main 메서드 말고 또다른 메서드에서 예외 처리를 해줘야할경우 메서드마다 try-catch문이 붙어야하는데 코드 중복이 발생한다.
그래서
예외 처리할 메서드를 따로 선언하고, 해당 메서드에 @ExceptionHandler 어노테이션을 붙이고 ,파라미터로 처리할 예외 종류를 선언하면. 해당 컨트롤러에서 nullPointerException 예외가 발생하면 해당 catcher2 메서드가 예외를 처리해준다. 이렇게 하면 컨트롤러에 예외처리를 해주는 부분에서 코드 중복을 면할수있다.
예외 페이지에 , 예외 메세지를 반환하려면 파라미터로 Model 을 선언해주고 error.jsp페이지에 예외 객체를 넘긴다
또는 request객체에 예외 객체를 저장해도된다.
🔰@ControllerAdvice 예외처리 방법 2
@ControllerAdvice("com.fastcampus.ch3") //지정된 패키지에서 발생한 에외만 처리
//@ControllerAdvice //파라미터 아무것도 안적으면 모든 페키지에 적용
public class GlobalCatcher {
@ExceptionHandler(.class)
public String catcher2(Exception ex , Model m) {
m.addAttribute("ex",ex);
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception{
throw new Exception("예외가 발생했습니다.");
}
위에서 @ExceptionHandler 사용해서 예외처리를 해주었던 방식은 해당 컨트롤로에서만 사용이 가능하다,
다른 컨트롤러에서 만약 1번 방법의 컨트롤러와 같은 예외처리를 해줘야한다면 또 똑같이 위에서 했던방식으로 예외처리를 해줘야한다.
이러한 수고를 덜기위해서, 예외처리를 해줄 전용 GlobalCatcher 예외 클래스를 만들고 , 해당 클래스에 @ControllerAdvice로 전역 예외 처리 에노테이션을 붙여준다.
매개변수로 지정된 패키지 이름을 주면, 지정된 패캐지 범위에서만 해당 예외처리를 하게 해줄수있다
🔰@ResponseStatus 상태 코드 바꾸기
@Controller
public class ExceptionController
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //200 -> 500 으로 상태 코드 변경
public String catcher(Exception ex, Model m) {
m.addAttribute("ex",ex);
return "error";
}
@RequestMapping("/ex")
public String main() throws Exception{
throw new Exception("예외가 발생했습니다.");
}
main메서드에서 예외가 발생해 , 예외처리 메서드가 예외를 처리해주고 "error" 뷰를 응답 해주었기 떄문에 http 응답 상태코드는 200번 ok 이다,
예외는 성공적으로 처리가 되었으나, 클라이언트가 원래 요청한 내용이 처리가 안됐기떄문에 200 응답 상태 코드는 적절하지않다.이럴떄 우리는 @ResponseStatus 어노테이션을 붙이면 응답 상태코드를 변경할수있다. default 값은 500이고, 파라미터에 원하는 예외 종류를 선언하면 그에 맞게 상태코드를 변경할수있다.
🔰 isErrorPage="true"
또 error.jsp 페이지에 해당 사진 빨간색 page contentType에 isErrorPage="true"를 주면 -> 이 jsp페이지는 에러가 났을떄 보여주는 페이지라는 의미이다. 저렇게 작성을 해주면 , 컨트롤러에서 model을 사용해 예외를 넘겨주지 않아도, 해당 jsp 페이지에서 기본 객체인 pageContext.exception 에 값이 저장이 되어서 사용할수있다
🔰Spring의 예외처리 흐름
클라이언트가 /ch2/ex로 요청 하면 => DispatcherServlet 이 => 해당 controller 한테 연결해주고 거기서 예외가 발생하면 => 다시 dispatcherServlet 에게 예외를 주면 DispatcherServlet이 예외를 처리하려고 handlerExceptionResolvers로 등록되어 있는 애들은 확인한다.
- ExceptionHandlerExceptionResolver: 에러 응답을 위한 Controller나 ControllerAdvice에 있는 ExceptionHandler를 처리함
- ResponseStatusExceptionResolver: Http 상태 코드를 지정하는 @ResponseStatus 또는 ResponseStatusException를 처리함
- DefaultHandlerExceptionResolver: 스프링 내부의 기본 예외들을 처리한다.
참고
https://mangkyu.tistory.com/204
[Spring] 스프링의 다양한 예외 처리 방법(ExceptionHandler, ControllerAdvice 등) 완벽하게 이해하기 - (1/2)
예외 처리는 애플리케이션을 만드는데 매우 중요한 부분을 차지한다. Spring 프레임워크는 매우 다양한 에러 처리 방법을 제공하는데, 어떠한 방법들이 있고 가장 좋은 방법(Best Practice)은 무엇인
mangkyu.tistory.com
스프링의 정석 남궁성
'Develop > Spring' 카테고리의 다른 글
[Spring] Bean/component-scan 동작 과정 (0) | 2024.08.29 |
---|---|
[Spring] Spring vs Springboot 차이 (0) | 2024.06.02 |
[Spring] 스프링 xml 설정 파일 - web.xml, root-context.xml, servlet-context.xml 차이 (0) | 2024.05.21 |
[Spring] DAO,DTO,VO 알아보기 (0) | 2024.03.13 |
[Spirng] Spring MVC 프로젝트 폴더 구조와 실행 순서 and DispatcherServlet 소스 분석 (0) | 2024.02.20 |