Exception

Controller 에서 Exception 은 횡단관심사이다.

따라서 Exception 처리를 전담하는 method 를 선언할 수 있다.

@ExceptionHandler(InvalidDataException.class)
public ResponseEntity<Map<String, Object>> handleInvalidDataException(InvalidDataException e) {
    Map<String, Object> body = ResponseUtils.simple(false, "데이터가 올바르지 않습니다.", e);
    return ResponseEntity.badRequest().contentType(MediaType.APPLICATION_JSON).body(body);
}

위에서는 하나의 Exception type 에 대한 점담 처리를 맡았지만, 하나의 method 가 여러 Exception 에 대한 처리를 할 수 있다.

위치

만약, @ExceptionHandler 가 붙은 method 가 어느 @Contoller 내부에 위치하면, 해당 method 는 해당 Contoller 안에서 발생한 Exception 만 책임진다.

그러나, 어플리케이션의 여러 Controller 들에서 발생하는 Exception 들을 전역적으로 처리하고픈 needs가 있을 수 있다.

그런 경우, @ControllerAdvice 를 class level 로 달고, @ExceptionHandler 가 달린 method 들을 @ControllerAdvice 가 달린 class 내부로 집어넣는다.

package kr.co.swedenhouse.mama.controller.advice;

import kr.co.swedenhouse.mama.util.exception.InvalidDataException;
import kr.co.swedenhouse.mama.util.mvc.ResponseUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.mail.MessagingException;
import java.util.Map;

@ControllerAdvice
public class GenericAdvice {

    @ExceptionHandler(InvalidDataException.class)
    public ResponseEntity<Map<String, Object>> handleInvalidDataException(InvalidDataException e) {
        Map<String, Object> body = ResponseUtils.simple(false, "데이터가 올바르지 않습니다.", e);
        return ResponseEntity.badRequest().contentType(MediaType.APPLICATION_JSON).body(body);
    }

    @ExceptionHandler(MessagingException.class)
    public ResponseEntity<Map<String, Object>> handleMessagingException(MessagingException e) {
        Map<String, Object> body = ResponseUtils.simple(false, "이메일을 보내던 중 오류가 발생했습니다.", e);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON).body(body);
    }

}

물론, 완전 전역적으로 hooking 하지 않고, 특정 조건에서만 그렇게 하게끔 조건을 설정할 수도 있다. 그러나 default는 완전 전역적이다.

참고

results matching ""

    No results matching ""