Hello, Freakin world!

@RestControllerAdvice 를 이용해서 예외 처리하기 본문

Spring boot

@RestControllerAdvice 를 이용해서 예외 처리하기

johnna_endure 2020. 7. 12. 00:14

@ControllerAdvice란?

간단하게 말하자면 @ExceptionHandler, @ModelAttribute, @InitBinder 가 적용된 메서드들을 AOP를 적용해

컨트롤러 단에 적용하기 위해 고안된 애너테이션 입니다.

 

@RestControllerAdvice란?

@ResponseBody + @ControllerAdvice => @RestControllerAdvice 

 

 

 

우선 HelloException 이라는 간단한 예외를 만듭니다.

public class HelloException extends RuntimeException{
	public HelloException() {
		super("Hello, Exception!");
	}
}

 

다음은 컨트롤러를 만들고 해당 메서드에서 위의 예외를 던지게 합니다.

@RestController
public class HelloRestController {

	@GetMapping("/hello")
	public void throwException() {
		throw new HelloException();
	}
}

 

이제 앱을 시작해서 http://localhost:8080/hello 입력해서 일단 어떤 화면이 나오는지 관찰합니다.

 

 

기본 에러 페이지

 

Whitelabel Error Page 라고 하는 페이지가 나왔습니다. 이는 스프링부트에서 제공하는 기본 에러 페이지입니다.

 

이제 예외 처리 메서드를 작성하겠습니다.

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice(annotations = RestController.class)
public class HelloControllerAdvice {

	@ExceptionHandler
	public String errorHandler(HelloException e) {
		return e.getMessage();
	}
}

 

@RestControllerAdvice 에 annotations 속성에 컨트롤러 클래스를 인수로 주면 적용되는 범위를 해당 컨트롤러 클래스로 한정할 수 있습니다. 아무런 값도 주지 않으면 전역적으로 작동합니다.

 

@ExcepionHandler 메서드에 타겟이 되는 예외를 파라미터로 넘겼습니다.  타겟 예외가 발생되면 이 메서드가 호출됩니다.

간단하게 예외 메세지가 반환되도록 했습니다.

 

다시 앱을 실행시키고 /hello로 들어가보면,

 

예외가 처리됐습니다!

 

하나의 메서드로 복수의 예외를 처리하고 싶다면?

	@GetMapping("/hello")
	public void throwException() {
		throw new HelloException();
	}

	@GetMapping("/hello2")
	public void throwException2(){
		throw new NoSuchElementException("no element");
	}

 

/hello2 를 추가했습니다.

 

아래는 수정한 핸들러 메서드입니다.

	@ExceptionHandler(value = {HelloException.class, NoSuchElementException.class})
	public String errorHandler(RuntimeException e) {
		return e.getMessage();
	}

 

@ExceptionHandler 의 value 속성에 타겟 예외들을 넘겨줬습니다. 이제는 이 값들은 ExceptionHandler의 매치 범위를 결정합니다.  즉, 이전의 예제에서는 메서드의 파라미터에 예외가 매치되어 메서드가 호출됐지만, 이제는 value 속성의 값들이 이 역할을 대신하게 됩니다. (RuntimeException이 컨트롤러에서 직접 던져져도 errorHandler()는 호출되지 않습니다! )

 

메서드의 파라미터에는 HelloException, NoSuchElementException 의 공통 타입인 RuntimeException으로 받았습니다.

메서드 바디 내에서 HelloException와 NoSuchElementException를 직접 참조하고 싶으면  getCause() 를 이용해 추적합니다. 

 

hello2도 처리됐습니다.

 

 

Comments