가장 널리 쓰이는 예외처리 방법으로 try-catch 예외 처리가 있다.
Spirng boot 프로젝트를 하나 만들고 컨트롤러 파일을 하나 만들어서 Get을 수행하도록 만들어 보자.
package org.example.exception.Controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping(path = "api")
public class RestApiController {
@GetMapping(path = "")
public void hello(){
var list = List.of("hello");
try{
var element = list.get(1);
} catch (Exception e) {
log.info("",e);
}
}
}
이와 같이 try-catch로 예외처리를 수행하는 것을 가장 먼저 배웠을 것 이다.
이제 이러한 예외처리를 글로벌하게 처리해보자.
package org.example.exception.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice(basePackages = "org.example.exception.Controller") //RestApi가 사용되는 곳에 예외가 발생하는 것을 감지하는 어노테이션이다. 여기서는 basePackages를 지정해줌으로써 지정된 패키지에서의 예외만을 감지한다.
public class RestApiExceptionHandler {
@ExceptionHandler(value = {Exception.class}) //어떠한 예외를 잡을지 지정한다. 여기서는 모든 예외를 잡는다.
public ResponseEntity exception(Exception e){
log.error("RestApuExceptionHandler",e); //Logging Error
return ResponseEntity.status(200).build(); // Body가 없는 정상응답 200을 반환
}
@ExceptionHandler(value = {IndexOutOfBoundsException.class}) //특정한 예외를 잡는다. 여기서는 IndexOutOfBoundsException 에러를 잡는다.
public ResponseEntity outOfBound(
IndexOutOfBoundsException e //해당 예외를 받는다.
){
log.error("IndexOutOfBoundsException",e); //Logging Error
return ResponseEntity.status(200).build(); // Body가 없는 정상응답 200을 반환
}
}
설명: 이 어노테이션을 붙여줌으로서 Spring의 전역적인 예외를 처리할 수 있다.
비슷한 어노테이션으로 ControllerAdvice가 있다.
둘의 차이는 ControllerAdvice는 Spring3.2부터
RestControllerAdvice는 Spring4.3부터 제공된다는 점이고
RestControllerAdvice는 @ResponseBody가 붙어있어 응답을 JSON 형식으로 메서드에 보내준다.
설명: 이 어노테이션을 붙여주면 이 메서드가 어떠한 예외를 처리할지 지정해줄 수 있다.
첫번째 exception메서드에서는 Exception을 상속 받는 예외 즉 어떠한 예외이던 다 받겠다는 의미이고,
두번째 outOfBound메서드에서는 IndexOutOfBoundsException을 상속받는 예외를 받겠다는 의미이다.
그 다음 각 메서드의 파라미터로 받아지는 Exception과 IndexOutOfBoundsException은 각각의 @RestControllerAdvice에서 넘어노는 값들이다.