Spring MVC에서의 예외 처리 기법
기본적인 SpringBoot 예외 처리 방식
WAS(톰캣) ➜ 필터 ➜ 서블릿(디스패처 서블릿) ➜ 인터셉터 ➜ 컨트롤러 ➜ 컨트롤러(예외발생)
➜ 인터셉터 ➜ 서블릿(디스패처 서블릿) ➜ 필터 ➜ WAS(톰캣) ➜ WAS(톰캣) ➜ 필터 ➜ 서블릿(디스패처 서블릿) ➜ 인터셉터 ➜ 컨트롤러(BasicErrorController)
- WAS(톰캣) ➜ 필터
✔ 클라이언트의 요청이 웹 애플리케이션서버(WAS)로 도착하면 먼저 등록된 필터들이 요청을 가로챔
- 필터 ➜ 서블릿(디스패처 서블릿)
✔ 필터가 요청을 처리한 후, 해당 요청을 서블릿으로 전달
➜ 디스패처 서블릿은 요청을 적절한 컨트롤러로 라우팅 하고, 컨트롤러에서 비즈니스 로직을 처리
- 서블릿(디스패처 서블릿) ➜ 인터셉터
✔ 컨트롤러로 요청이 전달되면 등록된 인터셉터들이 작동
➜ 인터셉터는 컨트롤러가 요청을 처리하기 전과 후에 실행되는 로직을 구현할 수 있음
- 인터셉터 ➜ 컨트롤러(예외발생)
✔ 컨트롤러에서 예외가 발생하면 해당 예외를 처리할 수 있는 핸들러가 있는지 확인
➜ 핸들러가 있으면 예외를 핸들러로 전달하여 예외 처리 로직 실행
- 컨트롤러 ➜ 인터셉터
✔ 예외 처리가 완료되면 다시 인터셉터로 돌아와서 후처리 로직
- 인터셉터 ➜ 서블릿(디스패처 서블릿)
✔ 인터셉터에서 모든 처리가 완료되면 다시 서블릿으로 돌아가서 컨트롤러의 처리 결과를 받음
- 서블릿(디스패처 서블릿) ➜ 필터
✔ 서블릿이 응답을 생성하면 다시 등록된 필터들이 응답을 가로채서 후처리 작업 수행
- 필터 ➜ WAS(톰캣)
✔ 필터의 모든 작업이 완료되면 최종적으로 응답이 클라이언트에게 전달
- WAS(톰캣) ➜ 필터
✔ 클라이언트가 받은 응답이 다시 WAS로 돌아오면 등록된 필터들이 응답을 가로챔
➜ 추가적인 후처리
- 필터 -> 서블릿(디스패처 서블릿) ➜ 인터셉터
✔ 응답을 가로챈 필터가 다시 서블릿으로 요청을 보내고, 이어서 등록된 인터셉터가 응답 후처리 작업 수행
- 인터셉터 ➜ 컨트롤러(BasicErrorController)
✔ 응답을 최종적으로 처리할 때, 오류가 발생하면 Spring에서는 "BasicErrorController"라는 기본 오류 처리 컨트롤을 사용하여 오류 페이지를 제공
내용 참고 - 망나니 개발자 -
Spring이 제공하는 다양한 예외 처리 방법
spring에서는 공통 관심사(cross-cutting concerns)를 메인로직으로부터 분리하는
다양한 예외 처리 방식을 고안하였고, 예외처리 전략을 추상화한
HandlerExceptionResolver 인터페이스를 만들었다.
대부분의 HandlerExceptinonResolver는 발생한 Exception을 catch하고
HTTP 상태나 응답 메시지 등을 설정한다.
그래서 WAS 입장에서는 해당 요청이 정상적인 응답인 것처럼 인식되며,
위에서 설명한 복잡한 WAS의 에러 전달이 진행되지 않는다.
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex);
}
handler : 예외가 발생한 컨트롤러 객체
예외가 던져지면 디스패처 서블릿까지 전달되는데, 적합한 예외 처리를 위해
HandlerExceptionResolver 구현체들을 빈으로 등록하여 관리한다.
빈으로 등록된 4가지 구현체
DefaultErrorAttributes
에러 속성을 저장
ExceptionHandlerExceptionResolver
에러 응답을 위한 Controller나
ControllerAdvice에 있는 ExceptionHandler를 처리
ResponseStatusExceptionResolver
Http 상태 코드를 지정하는
@ResponseStatus 또는 ResponseStatusException을 처리
DefaultHandlerExceptionResolver
스프링 내부의 기본적인 예외 처리
@ResponseStatus
에러 HTTP 상태를 변경
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class NoSuchElementFoundException extends RuntimeException {
...
}
@ResponseStatusException
@GetMapping("/product/{id}")
public ResponseEntity<Product> getProduct(@PathVariable String id) {
try {
return ResponseEntity.ok(productService.getProduct(id));
} catch (NoSuchElementFoundException e) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Item Not Found");
}
}
@ExceptionHandler
매우 유연하게 에러를 처리할 수 있는 방법
@RestController
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
@GetMapping("/product/{id}")
public Response getProduct(@PathVariable String id){
return productService.getProduct(id);
}
@ExceptionHandler(NoSuchElementFoundException.class)
public ResponseEntity<String> handleNoSuchElementFoundException(NoSuchElementFoundException exception) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage());
}
}
ExceptionHandlerExceptionResolverd에 의해 처리
@RestController
@RequiredArgsConstructor
public class ProductController {
...
@ExceptionHandler(NoSuchElementFoundException.class)
public ResponseEntity<ErrorResponse> handleItemNotFoundException(NoSuchElementFoundException exception) {
...
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
...
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAllUncaughtException(Exception exception) {
...
}
}
내용 - 망나니 개발자 -
'컴퓨터 탐구' 카테고리의 다른 글
컴퓨터) 스택(Stack)과 큐(Queue) (0) | 2023.07.27 |
---|---|
컴퓨터) 웹 서버(Web Server)와 WAS(Web Application Serviece) (0) | 2023.07.27 |
네트워크) TCP와 UDP (0) | 2023.07.26 |
컴퓨터) REST API (0) | 2023.07.19 |
컴퓨터) CPU와 메모리 (0) | 2023.06.21 |