[Spring] ControllerAdvice

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));
}
Author: Song Hayoung
Link: https://songhayoung.github.io/2020/06/30/Spring/Controller_Advice/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.