사용자 도구

사이트 도구


springframework:mvc:controlleradvice

@ControllerAdvice

  • @ExceptionHandler, @InitBinder, @ModelAttribute를 여러 컨트롤러에 걸쳐 공통으로 설정할 수 있다.

@ExceptionHandler

package javabeat.net;
 
import java.io.IOException;
import java.sql.SQLException;
 
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 
@ControllerAdvice
public class ControllerAdviceTest {
    @ExceptionHandler(IOException.class)
    public ModelAndView handleIOException(IOException exception){
        ModelAndView andView = new ModelAndView();
        andView.setViewName("error");
        return andView;
    }
    @ExceptionHandler(SQLException.class)
    public ModelAndView handleSQLException(SQLException exception){
        ModelAndView andView = new ModelAndView();
        andView.setViewName("error");
        return andView;
    }
    // JSON 에러 내면서 Http Status Code 변경
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<SomeErrorObject> exceptionHandler(Exception e) {
        // org.springframework.http.HttpStatus 를 참조할 것.
        HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        SomeErrorObject errorObject = new SomeErrorObject();
 
        return new ResponseEntity<>(errorObject, httpStatus);
    }
}

Parameter Validation/Binding Exception 처리

@Valid 에 의한 파라미터 Validation 오류 핸들러

@ControllerAdvice
public class RestErrorHandler {
 
    private MessageSource messageSource;
 
    @Autowired
    public RestErrorHandler(MessageSource messageSource) {
        this.messageSource = messageSource;
    }
 
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();
 
        return processFieldErrors(fieldErrors);
    }
 
    private ValidationErrorDTO processFieldErrors(List<FieldError> fieldErrors) {
        ValidationErrorDTO dto = new ValidationErrorDTO();
 
        for (FieldError fieldError: fieldErrors) {
            String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
            dto.addFieldError(fieldError.getField(), localizedErrorMessage);
        }
 
        return dto;
    }
 
    private String resolveLocalizedErrorMessage(FieldError fieldError) {
        Locale currentLocale =  LocaleContextHolder.getLocale();
        String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);
 
        //If the message was not found, return the most accurate field error code instead.
        //You can remove this check if you prefer to get the default error message.
        if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
            String[] fieldErrorCodes = fieldError.getCodes();
            localizedErrorMessage = fieldErrorCodes[0];
        }
 
        return localizedErrorMessage;
    }
}

BindingException 처리

  • BindException 은 Controller에서 쿼리 파라미터를 객체로 변환할 때 타입이 다르던가 날짜 포맷팅이 잘못됐던가 할 때 발생한다.
@ExceptionHandler(BindException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ExDto handleBindException(BindException e) {
  // BindException이 BindingResult, Errors를 상속하고 있으므로 해당 데이터를 꺼내서 사용하면 된다.
}

주요 Spring MVC Exception에 대해 오버라이드 하지 말 것

ResponseBodyAdvice, RequestBodyAdvice

참고

springframework/mvc/controlleradvice.txt · 마지막으로 수정됨: 2021/07/14 12:49 저자 kwon37xi