토이 프로젝트 스터디 #8
- 스터디 진행 날짜 : 6/14
- 스터디 작업 날짜 : 6/11 ~ 6/14
토이 프로젝트 진행 사항
- 예외 처리
ControllerAdvice
공통 처리
messageSource
적용
Account
관련 테스트 코드 작성
내용
AdviceController
@RequiredArgsConstructor
public class ControllerAdviceUtils {
private final MessageSource messageSource;
public Map<String, String> getFailureResponse(ExceptionType exceptionType) {
return new HashMap<>() {
{
put("code", getCode(exceptionType.getCode()));
put("message", getMessage(exceptionType.getMessage()));
}
};
}
public Map<String, String> getFailureResponse(ExceptionType exceptionType, Object... args) {
return new HashMap<>() {
{
put("code", getCode(exceptionType.getCode()));
put("message", getMessage(exceptionType.getMessage(), args));
}
};
}
private String getCode(String key) {
return messageSource.getMessage(key, null, null);
}
private String getMessage(String key) {
return messageSource.getMessage(key, null, LocaleContextHolder.getLocale());
}
private String getMessage(String key, Object... args) {
return messageSource.getMessage(key, args, LocaleContextHolder.getLocale());
}
}
ControllerAdvice
의 경우 동일한 구조로 예외를 표시하므로 이를 공통으로 처리할 수 있도록 ControllerAdviceUtils
사용
messageSource
에서 값 조회
- 오버로딩을 통해 메세지가 다양한 경우와 아닌 경우를 구분
{
"code": "1003",
"message": "비밀번호를 입력해주세요."
}
- 위와 같은 양식으로 예외 출력
code
: 예외에 대한 내용을 표로 정리하기 위해 추가
message
: 해당 예외에 대한 설명
예외 메세지
- 예외 메세지에
messageSource
적용
- 예외와 관련된 예외 메세지나 예외 코드를 하나의 파일에서 관리하기 위함
# exception_code.properties
accountEmailAlreadyExistsException.code=1001
accountNicknameAlreadyExistsException.code=1002
methodArgumentNotValidException.code=1003
accountWithdrawalException.code=1004
# exception_message.properties
accountEmailAlreadyExistsException.message=이미 존재하는 이메일입니다.
accountNicknameAlreadyExistsException.message=이미 존재하는 닉네임입니다.
methodArgumentNotValidException.message={0}
accountWithdrawalException.message=이미 탈퇴한 이메일입니다.
# validation_message
# Account Entity Validate Common Message
email.notBlank=이메일을 입력해주세요.
email.email=이메일 형식으로 입력해주세요.
password.notBlank=비밀번호를 입력해주세요.
nickname.notBlank=닉네임을 입력해주세요.
- 각 필요에 따라
properties
를 구분하여 작성
@Getter
public enum ExceptionType {
ACCOUNT_EMAIL_ALREADY_EXISTS_EXCEPTION("accountEmailAlreadyExistsException.code", "accountEmailAlreadyExistsException.message"),
METHOD_ARGUMENT_NOT_VALID_EXCEPTION("methodArgumentNotValidException.code", "methodArgumentNotValidException.message"),
ACCOUNT_NICKNAME_ALREADY_EXISTS_EXCEPTION("accountNicknameAlreadyExistsException.code", "accountNicknameAlreadyExistsException.message"),
ACCOUNT_WITHDRAWAL_EXCEPTION("accountWithdrawalException.code", "accountWithdrawalException.message");
private final String code;
private final String message;
ExceptionType(String code, String message) {
this.code = code;
this.message = message;
}
- 작성한
properties
를 enum
을 통해 관리
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
@Bean
public MessageSource controllerAdviceMessageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:message/exception_message", "classpath:message/exception_code");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public MessageSource validatorMessageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:message/validation_message");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Override
public Validator getValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(validatorMessageSource());
return validator;
}
@Bean
public ControllerAdviceUtils utils() {
return new ControllerAdviceUtils(controllerAdviceMessageSource());
}
}
WebMvcConfigurer
를 통해 설정 추가
@Slf4j
@RequiredArgsConstructor
@RestControllerAdvice(assignableTypes = {AccountController.class})
public class AccountRestControllerAdvice {
private final ControllerAdviceUtils utils;
@ExceptionHandler(AccountNotFoundException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
Map<String, String> accountNotFoundExceptionHandler() {
return utils.getFailureResponse(ExceptionType.ACCOUNT_NOT_FOUND_EXCEPTION);
}
}
- 위와 같이
ControllerAdvice
에서 사용