1. 개요

Java의 예외는 프로그램에서 문제가 발생했음을 알리는 데 사용됩니다. 예외를 던지는 것 외에도 추가 정보를 제공하기 위해 메시지를 추가할 수도 있습니다.

이 기사에서는 getLocalizedMessage 메소드를 활용 하여 영어와 프랑스어로 예외 메시지를 제공할 것입니다.

2. 리소스 번들

우리는 사용하여 메시지를 조회 할 수있는 방법이 필요 messageKey을 메시지와 식별하는 로케일을 에 대한 값 제공되는 번역 식별 할 수 messageKey을 . 영어 및 프랑스어 메시지 번역을 검색하기 위해 ResourceBundle에 대한 액세스를 추상화하는 간단한 클래스를 만들 것입니다 .

public class Messages {

    public static String getMessageForLocale(String messageKey, Locale locale) {
        return ResourceBundle.getBundle("messages", locale)
          .getString(messageKey);
    }

}

우리의 메시지 클래스 사용은 ResourceBundle을 우리의 클래스 패스의 루트에 우리의 번들로 특성 파일을로드 할 수 있습니다. 두 개의 파일이 있습니다. 하나는 영어 메시지용이고 다른 하나는 프랑스어 메시지용입니다.

# messages.properties
message.exception = I am an exception.
# messages_fr.properties
message.exception = Je suis une exception.

3. 현지화된 예외 클래스

우리의 예외 서브 클래스는 기본 사용 로케일을 우리의 메시지에 사용할 번역을 결정합니다. Locale#getDefault 를 사용하여 기본 로케일얻습니다 .

애플리케이션이 서버에서 실행 중이라면 기본값을 설정하는 대신 HTTP 요청 헤더를 사용하여 사용할 로케일식별합니다 . 이를 위해 우리는 Locale 을 받아들이는 생성자를 만들 것 입니다.

Exception 하위 클래스를 생성해 보겠습니다 . 이를 위해 RuntimeException 또는 Exception을 확장할 수 있습니다 . Exception을 확장 하고 getLocalizedMessage를 재정의 합시다 .

public class LocalizedException extends Exception {

    private final String messageKey;
    private final Locale locale;

    public LocalizedException(String messageKey) {
        this(messageKey, Locale.getDefault());
    }

    public LocalizedException(String messageKey, Locale locale) {
        this.messageKey = messageKey;
        this.locale = locale;
    }

    public String getLocalizedMessage() {
        return Messages.getMessageForLocale(messageKey, locale);
    }
}

4. 모든 것을 합치기

모든 것이 작동하는지 확인하기 위해 몇 가지 단위 테스트를 만들어 보겠습니다. 건설 중 예외에 사용자 지정 로케일전달하는지 확인하기 위해 영어 및 프랑스어 번역에 대한 테스트를 생성합니다 .

@Test
public void givenUsEnglishProvidedLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessage() {
    LocalizedException localizedException = new LocalizedException("message.exception", Locale.US);
    String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception.");
}

@Test
public void givenFranceFrenchProvidedLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() {
    LocalizedException localizedException = new LocalizedException("message.exception", Locale.FRANCE);
    String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception.");
}

우리의 예외는 기본 로케일사용할 수 있습니다 . 기본 로케일 기능이 작동 하는지 확인하기 위해 두 가지 테스트를 더 만들어 보겠습니다 .

@Test
public void givenUsEnglishDefaultLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessages() {
    Locale.setDefault(Locale.US);

    LocalizedException localizedException = new LocalizedException("message.exception");
    String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception.");
}

@Test
public void givenFranceFrenchDefaultLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() {
    Locale.setDefault(Locale.FRANCE);

    LocalizedException localizedException = new LocalizedException("message.exception");
    String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception.");
}

5. 주의 사항

5.1. 던질 수 있는 물건 기록하기

예외 인스턴스를 로그 로 보내는 데 사용하는 로깅 프레임워크를 염두에 두어야 합니다 .

Log4J, Log4J2 및 Logback은 getMessage사용 하여 로그 어펜더에 쓸 메시지를 검색합니다. java.util.logging 을 사용하는 경우 내용은 getLocalizedMessage 에서 가져 옵니다 .

어떤 로깅 구현이 사용되는지에 대해 걱정할 필요가 없도록 getLocalizedMessage 를 호출하기 위해 getMessage재정의하는 것을 고려할 수 있습니다 .

5.2. 서버측 애플리케이션

클라이언트 애플리케이션에 대한 예외 메시지를 현지화할 때 한 시스템의 현재 Locale 만 걱정하면 됩니다 . 그러나 서버 측 애플리케이션에서 예외 메시지를 현지화하려면 기본 로케일 을 전환하면 애플리케이션 서버 내의 모든 요청에 ​​영향을 미친다는 점을 염두에 두어야 합니다.

예외 메시지를 현지화하기로 결정한 경우 예외에 대해 생성자를 생성하여 Locale 을 수락합니다 . 이렇게 하면 기본 Locale 을 업데이트하지 않고 메시지를 현지화할 수 있습니다.

6. 요약

예외 메시지를 현지화하는 것은 매우 간단합니다. 우리가 해야 할 일은 메시지에 대한 ResourceBundle 을 만든 다음 Exception 하위 클래스 에서 getLocalizedMessage 를 구현 하는 것 입니다.

평소와 같이 예제는 GitHub에서 사용할 수 있습니다 .

Junit footer banner