@ExceptionHandler
, @InitBinder
, @ModelAttribute
를 여러 컨트롤러에 걸쳐 공통으로 설정할 수 있다.@ControllerAdvice
에 각종 예외 처리 핸들러(@ExceptionHandler
)를 미리 등록해 두고 component-scan을 하면 자동 에러 처리가 된다.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); } }
@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; } }
@ExceptionHandler(BindException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ExDto handleBindException(BindException e) { // BindException이 BindingResult, Errors를 상속하고 있으므로 해당 데이터를 꺼내서 사용하면 된다. }
ControllerAdvice
나 ExceptionHandler
를 override 했을 경우 Spring이 기본으로 지정한 에러코드가 아닌 다른 에러코드로 응답 코드가 내려갈 수도 있다.