💡 SpringBoot가 제공하는 ExceptionResolver
1. ExceptionHandlerExeptionResolver
@ExceptionHandler 처리 > API 예외처리
2. ResponseStatusExceptionResolver
@ResponseStatus(value=HttpStatus.NOT_FOUND) Http 상태코드를 지정해준다.
3. DefaultHandlerExceptionResolver
스프링 내부 기본 예외를 처리한다.
☝ ExceptionHandler
@Target ( 값 = METHOD )
@Retention ( 값 = RUNTIME )
@Documented
public @interface ExceptionHandler
특정 핸들러 클래스 또는 핸들러 메서드에서 예외를 처리하기 위한 annotation
@Controller, @RestController가 적용된 Bean에서 발생하는 예외를 잡는다.
@ExceptionHandler(value = RuntimeException.class)
public String handle(RuntimeException ex) {
return "RuntimeException";
}
value에 어떤 예외를 잡을 지 설정한다. value를 지정하지 않으면 모든 예외를 잡는다.
@ExceptionHandler({NullpointerException.class, IOException.clss})
처럼 List형태로 예외를 정할 수도 있다.
👉 적용예시
@GetMapping("/getInfo")
public ResponseEntity getInfo(@RequestParam("id") String id) throws Exception {
if(id.equals("ex"))
throw new RuntimeException();
return new ResponseEntity(HttpStatus.OK);
}
@ExceptionHandler(value = RuntimeException.class)
public String handle(RuntimeException ex) {
return "RuntimeException";
}
Controller에서 RuntimeException이 발생하면 ExceptionHandler를 호출한다.
다른 컨트롤러에서 Exception발생시 동직하지 않으므로 해당 컨트롤러에서도 구현을 해줘야 한다.
똑같은 기능을 반복하는 것을 피하기 위해 @ControllerAdvice를 적용할 수 있다.
☝ @ControllerAdvice
@Controller에서 발생하는 예외를 잡을 수 있다. 새로운 클래스를 만들어서 사용할 수 있다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};
}
패키지 상관없이 전역에서 사용할 수 있다.
☝ @RestControllerAdvice
@ControllerAdvice와 동일한데 응답의 Body에 객체를 넣어서 반환할 수 있다. @RestController와 @Controller모두 예외를 잡을 수 있다. @ResponseBody를 통해 객체를 리턴할 수 있다는 뜻이다.
@RestControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(value = RuntimeException.class)
public ResponseEntity handle(RuntimeException ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
@ExceptionHandler(DataAccessException.class)
public ResponseEntity<String> dataExceptionHandle() {
return ResponseEntity.badRequest().build();
}
}
☝ ResponseStatusExceptionResolver
- @ResponseStatus
- ResponseStatusException
위의 두 가지 경우를 처리한다.
🙂@ResponseStatus
@Slf4j
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public class CommonBadRequestException extends RuntimeException{
public CommonBadRequestException(String message) {
super(message);
}
}
RuntimeException을 상속 받아서 구현한다.
ResponseStatus에 응답할 코드를 넣으면 된다.
@GetMapping("/resEx")
public void resEx() {
throw new CommonBadRequestException("RES Exception");
}
resEx를 호출하면 500이 리턴된다.
⛔ @ExceptionHandler에 에러가 설정되어 있으면 우선순위가 더 높다.
ERROR Controller 설정할 경우 /error가 호출되서 ErrorController에 설정된 @ResponseStatus가 우선순위가 높다.
👇 ErrorController 설정방법
출처: https://tweety1121.tistory.com/entry/Spring-boot-thymeleaf-로-Error페이지-처리 [Pli's 개발일기]
🙂ResponseStatusException
ResponseStatus의 경우 ActorNotFoundException이 발생하면 동일한 오류메시지와 상태코드를 생성한다.
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Actor Not Found")
public class ActorNotFoundException extends Exception {
// ...
}
예외와 긴말한 결합이 생긴다.
@GetMapping("/actor/{id}")
public String getActorName(@PathVariable("id") int id) {
try {
return actorService.getActor(id);
} catch (ActorNotFoundException ex) {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "Actor Not Found", ex);
}
}
대안으로 ResponseStatusException을 생성하여 사용하면 동일한 유형의 예외라도 별도로 처리할 수 있고
다른 상태코드를 설정할 수 있어서 긴밀한 결합을 줄일 수 있다.
'Spring' 카테고리의 다른 글
Spring MVC 동작 방식 (DispatcherServlet) (0) | 2022.01.27 |
---|---|
Spring boot thymeleaf 로 Error페이지 처리 (0) | 2022.01.27 |
Spring Boot QR코드 이미지 생성 해서 thymeleaf로 보여주기 (0) | 2021.12.16 |
resilience4j circuit breaker test (with spring boot) (0) | 2021.04.09 |
SpringBoot 외부 프로퍼티 파일로 실행하기 (application.properties) (0) | 2021.01.27 |