토이 프로젝트 스터디 #8

appti·2022년 6월 14일
0

토이 프로젝트 스터디 #8

  • 스터디 진행 날짜 : 6/14
  • 스터디 작업 날짜 : 6/11 ~ 6/14

토이 프로젝트 진행 사항

  • 예외 처리
    • ControllerAdvice 공통 처리
    • messageSource 적용
  • Account 관련 테스트 코드 작성

내용

AdviceController

  • 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;
    }
  • 작성한 propertiesenum을 통해 관리
@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에서 사용
profile
안녕하세요

0개의 댓글