ControllerAdvice
컨트롤러에서 발생하는 예외를 처리하기 위해 존재한다 컨트롤러 레벨에서 각각의 예외를 처리할 수 있지만 여러 컨트롤러에서 공동으로 발생하는 예외의 경우 ControllerAdvice에서 글로벌하게 처리하는것이 깔끔하다
RestControllerAdvice @ControllerAdvice + @ReponseBody
의 구조이다
ControllerAdvice에서 예외 처리 하기 컨트롤러 레이어에서 @Valid
를 통한 검증을 통해 입력값을 검증하고 예외를 처리할 수 있다 또한 하위 레이어에서 예외 발생시 컨트롤러 레이어에서 예외를 감싸 던지면 된다
1 2 3 4 5 6 7 8 9 10 11 @PostMapping("/login") public String postLogin (@Valid @RequestBody UserServiceDto.Login user) { try { userInfoService.loginUser(user); } catch (PasswordValidationFailureException e) { throw new PasswordValidationFailureException (); } return "redirect:/main" ; }
컨트롤러에서 던진 예외는 @ExceptionHandler
를 통해 예외를 받는다 개인적으로 예외 처리에 대해 결과값을 돌려주는 방법은 다양하나 Http 상태 코드를 사용하려고 노력한다
1 2 3 4 5 @ExceptionHandler(PasswordValidationFailureException.class) @ResponseBody public ResponseEntity<String> passwordValidationFailureError (PasswordValidationFailureException ex, Locale locale) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(messageSource.getMessage("userService.passwordValidationFailure" ,null ,locale)); }
@Valid
를 통해 조건에 일치하지 않은 파라미터를 검증하는 방법이다@Valid
에서 검증에 실패할 시 MethodArgumentNotValidException
이 발생한다 다음은 Validator를 통해 검증에 실패한 케이스에 대해 에러에서 디폴트 메세지를 가져와 i18n으로 메세지를 지역화해서 Http 상태코드를 같이 보내주는 방법이다
1 2 3 4 5 6 7 @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody public ResponseEntity<String> paramViolationError (MethodArgumentNotValidException ex, Locale locale) { logger.error(ex.getBindingResult().getFieldError().toString()); Object rejectvalue[] = {ex.getBindingResult().getFieldError().getRejectedValue()}; return ResponseEntity.badRequest().body(messageSource.getMessage(ex.getBindingResult().getFieldError().getDefaultMessage(),rejectvalue ,locale)); }