在Java中本地化異常消息
- java
- Exception
1.概述
Java中的異常用於表示程序中出現了問題。除了引發異常外,我們甚至可以添加一條消息以提供其他信息。
在本文中,我們將利用getLocalizedMessage
方法來提供英語和法語的異常消息。
2.資源包Resource Bundle
我們需要一種使用messageKey
標識消息並使用Locale
messageKey
提供值的轉換的查找消息的方法。我們將創建一個簡單的類來抽象化對ResourceBundle
訪問,以檢索英語和法語消息翻譯:
public class Messages {
public static String getMessageForLocale(String messageKey, Locale locale) {
return ResourceBundle.getBundle("messages", locale)
.getString(messageKey);
}
}
我們的Messages
類使用ResourceBundle
將屬性文件加載到我們的包中,該包位於我們的類路徑的根目錄下。我們有兩個文件-一個用於英語消息,一個用於法語消息:
# messages.properties
message.exception = I am an exception.
# messages_fr.properties
message.exception = Je suis une exception.
3.本地化的異常類
我們的Exception
子類將使用默認的Locale
來確定要為我們的消息使用的翻譯。我們將使用Locale#getDefault
獲得默認的Locale
。
如果我們的應用程序在服務器上運行,我們將使用HTTP請求標頭來標識Locale
,而不是設置默認語言環境。為此,我們將創建一個構造函數以接受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.放在一起
讓我們創建一些單元測試以驗證一切正常。我們將為英語和法語翻譯創建測試,以驗證Locale
傳遞給異常的方法:
@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.");
}
我們的異常也可以使用默認的Locale
。讓我們再創建兩個測試,以驗證默認的Locale
功能是否正常工作:
@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 日誌記錄框架
我們需要牢記用於將Exception
實例發送到日誌的日誌記錄框架。
Log4J,Log4J2和Logback使用getMessage
檢索消息以寫入日誌附加程序。如果我們使用java.util.logging
,則內容來自getLocalizedMessage
。
我們可能要考慮重寫getMessage
來調用getLocalizedMessage
因此我們不必擔心使用哪種日誌記錄實現。
5.2 服務器端應用程序
當我們為客戶端應用程序本地化異常消息時,我們只需要擔心一個系統的當前Locale
。但是,如果要在服務器端應用程序中本地化異常消息,則應記住,切換默認Locale
將影響應用程序服務器內的所有請求。
如果我們決定本地化異常消息,我們將在異常上創建一個構造函數以接受Locale
。這將使我們能夠在不更新默認Locale
的情況下本地化消息。
6.總結
本地化異常消息非常簡單。我們需要做的就是為我們的消息ResourceBundle
,然後在我們的Exception
子類中getLocalizedMessage