0. 환경
- 인텔리제이
- Spring Boot 2.5.6
- lombok 사용
- java 11(AdoptOpenJDK-11.0.11)
1. 사용할 주요 어노테이션
1.1. @RestControllerAdvice
- 모든 @Controller 즉, 전역에서 발생할 수 있는 예외를 잡아 처리해주는 어노테이션
- @Controller나 @RestController에서 발생한 예외를 한 곳에서 관리하고 처리할 수 있게 도와주는 어노테이션
- @RestControllerAdvice = @ControllerAdvice + @ResponseBody
- @RestControllerAdvice(basePackages = “com.test.api”) basePackage를 이용하여 특정 패키지 하위에만 적용할 수도 있습니다.
@RestControllerAdvice
public class ExceptionController {
// (...) 생략
}
1.2. @ExceptionHandler
- 지정한 예외 클래스를 받아서 해당 클래스 발생 시 특정 메서드를 실행해주는 어노테이션
- @Controller, @RestController가 적용된 Bean내에서 발생하는 예외를 잡아서 하나의 메서드에서 처리해주는 기능
- @ControllerAdvice, @RestControllerAdvice 명시된 클래스 내부 메서드에 사용합니다.
//Exception 예외 발생 시 ServerException 메소드 실행
@ExceptionHandler(Exception.class)
public Response ServerException(Exception e) {
return new Response("500", "서버 에러");
}
1.3. @ResponseStatus
Response Status Code를 지정할 수 있습니다.
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 상태코드 500 return
2. 예시 코드 작성
[예시]
http://localhost:8080/test?param=1 -> 커스텀 예외 발생
http://localhost:8080/test?param=2 -> ArithmeticException 예외 발생
없는 주소 -> NoHandlerFoundException 예외 발생
2.1 사용자 정의 예외 클래스(Custom Exception)
- RuntimeException를 상속하여 Custom Exception Class를 작성합니다.
//테스트 사용자 정의 예외
public class TestException extends RuntimeException {
public TestException() {
super();
}
public TestException(String message) {
super(message);
}
public TestException(String message, Throwable cause) {
super(message, cause);
}
public TestException(Throwable cause) {
super(cause);
}
protected TestException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
2.2. 예외 컨트롤러 작성(@RestControllerAdvice, @ExceptionHandler)
- @RestControllerAdvice, @ExceptionHandler, @ResponseStatus를 이용해 작성합니다.
import com.test.api.exception.TestException;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
@RestControllerAdvice
public class ExceptionController {
@ExceptionHandler(TestException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Response TestException(Exception e) {
e.printStackTrace();
return new Response("501", "테스트 커스텀 예외 입니다.");
}
@ExceptionHandler(ArithmeticException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Response ServerException(Exception e) {
e.printStackTrace();
return new Response("500", "서버 에러");
}
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Response NotFoundException(Exception e) {
e.printStackTrace();
return new Response("404", "찾을 수 없습니다.");
}
//Response DTO
@Data
@AllArgsConstructor
static class Response {
private String code;
private String msg;
}
}
2.3. 컨트롤러
import com.test.api.domain.Test;
import com.test.api.exception.TestException;
import com.test.api.service.TestService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@Log4j2
@RestController
@RequiredArgsConstructor
public class TestController {
@GetMapping(value = "/test")
public String test(@RequestParam(required = false) String param) throws Exception {
if(param.equals("1")) {
throw new TestException("테스트 예외 입니다.");
} else if(param.equals("2")) {
//ArithmeticException 발생
int div = 1/0;
}
return "success";
}
}
2.4. 404 예외를 위한 추가 설정
- resources/application.properties에 꼭 추가 설정해야 NoHandlerFoundException를 핸들링할 수 있습니다.
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
3. 결과
테스트를 위해 스프링 부트를 실행하고 웹 브라우저 또는 테스트 툴(Postman)을 이용해 확인해 봅니다.
[http://localhost:8080/test?param=1]
[http://localhost:8080/test?param=2]
[http://localhost:8080/test2(없는 주소)]
'Backend > Spring' 카테고리의 다른 글
[Spring Boot] 스프링 부트 Log4J2 취약점 조치 (Log4J2 버전 업데이트) (3) | 2021.12.13 |
---|---|
[Spring Boot] Filter 를 이용하여 Request Body 핸들링 (HttpServletRequestWrapper) (0) | 2021.12.09 |
[Spring Boot] 윈도우 스프링 부트 Gradle 프로젝트 jar 빌드 방법 (0) | 2021.11.30 |
[Spring Boot] 스프링 부트 필터 적용 (Filter) (0) | 2021.11.29 |
[Spring Boot] 스프링 부트 인터셉터 적용 (HandlerInterceptor) (0) | 2021.11.28 |