背景:企業項目中,往往面對國際的。針對不同地區語言,ResourceBundle主要用來處理本地化資源和國際化資源的問題,向用戶展示合理的界面顯示。
ResourceBundle
官方解釋:一堆有着相同前綴名稱但有着不同語言後綴名稱的屬性文件的集合,且至少包含2個有着相似前綴名稱的屬性文件。
用途:從適合當前用戶語言環境的資源包,一適應不同語言環境,後期提示語均在配置文件中,修改便捷。
配合Locale使用:查詢Java所支持的國家和語言,方便查詢強制化Local屬性。
package study;
import java.util.Locale;
import java.util.ResourceBundle;
public class Test {
public static void main(String[] args) {
Locale[] localeList = Locale.getAvailableLocales();
//遍歷數組的每個元素,依次獲取所支持的國家和語言
for (int i = 0; i < localeList.length ; i++ )
{
System.out.println(localeList[i].getCountry()+ "( "+localeList[i].getDisplayCountry() +") "
+localeList[i].getLanguage()+"("+localeList[i].getDisplayLanguage()+")");
}
}
加載順序
優先級:本地化資源(默認)>加載系統默認>加載默認的資源文件。
不存在:java.util.MissingResourceException。
本地資源構建:新建myconfig.properties相關文件
myconfig.properties:local=default
myconfig_zh_CN.properties:local=zh_CN
myconfig_en_US.properties:local=en_US
package study;
import java.util.Locale;
import java.util.ResourceBundle;
public class Test {
public static void main(String[] args) {
//取得系統默認的國家/語言環境
System.out.println("=================");
//獲取本地語言地區屬性
System.out.println("default:"+Locale.getDefault());
//加載默認src下,但是不能讀取其他文件加載,本class在src.study下,所以需要加前綴。
ResourceBundle resourceBundle0 = ResourceBundle.getBundle("study.myconfig");
System.out.println(resourceBundle0.getString("local"));
System.out.println("=================");
//中文測試
Locale locale1 = new Locale("zh", "CN");
ResourceBundle resourceBundle1 = ResourceBundle.getBundle("study.myconfig",locale1);
System.out.println(resourceBundle1.getString("local"));
System.out.println("=================");
//英文測試
Locale locale2 = new Locale("en", "US");
ResourceBundle resourceBundle2 = ResourceBundle.getBundle("study.myconfig",locale2);
System.out.println(resourceBundle2.getString("local"));
System.out.println("=================");
//德文測試,但不存在該語言的Properties
Locale locale3 = new Locale("de", "GR");
ResourceBundle resourceBundle3 = ResourceBundle.getBundle("study.myconfig",locale3);
System.out.println(resourceBundle3.getString("local"));
}
測試結果:
順序:對於中國用戶:中國>默認。英國用戶:英國>默認。 德國:中國>默認(德國不存在,但是不是直接走默認,而是先走中國,中國是本地化資源!!!)
特別:
1.屬性key-value,若上級資源中沒有key,則去下級資源中尋找。
2.優先走本地化資源文件。若不存在,則走不帶後綴文件,本地化資源文件不等於默認不帶後綴的配置文件。
刪除myconfig_zh_CN.properties:
順序:對於中國用戶:默認。英國用戶:英國>默認。 德國:默認(德國不存在,但是不是直接走默認,而是先走中國,中國是本地化資源!!!)
其他注意:
報錯:Can’t find bundle for base name myconfig, locale xx_XX。查找文件路徑是否正確。
- 直接配置,src下讀取,但是內部文件夾,需要前綴讀取。
- src路徑下的文件在編譯後會放到WEB-INF/clases路徑下(默認的classpath)
- 直接放到WEB-INF下的話,是不在classpath下的
編碼:
底層讀取Properties文件是根據字節流的形式,防止中文亂碼,建議配置文件存在中文等,使用Unicode字符集進行配置。
源碼片段:
else if (format.equals("java.properties")) {
final String resourceName = toResourceName0(bundleName, "properties");
if (resourceName == null) {
return bundle;
}
final ClassLoader classLoader = loader;
final boolean reloadFlag = reload;
InputStream stream = null;
try {
stream = AccessController.doPrivileged(
new PrivilegedExceptionAction<InputStream>() {
public InputStream run() throws IOException {
InputStream is = null;
if (reloadFlag) {
URL url = classLoader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
// Disable caches to get fresh data for
// reloading.
connection.setUseCaches(false);
is = connection.getInputStream();
}
}
} else {
is = classLoader.getResourceAsStream(resourceName);
}
return is;
}
});
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
}
經驗
1.可以通過只配置myconfig.properties來全局變量,不配置其他語言文件。
2.企業項目中,配合PropertyUtils,設置map.properties,不打包,當國際化各個配置文件找不到相應提示,提供一個類別管理的報錯。
3.編碼問題請使用Unicode字符集輸入,可以使用在線轉碼工具也可以配合java自帶的native2ascii.exe
4.配合NumberFormat ,DateFormat進行String處理
補充
Properties補充:
https://www.cnblogs.com/alfredinchange/p/5384760.html
ResourceBundle運行會自行將配置文件打包,也可以根據情況自己配合idea打包:https://segmentfault.com/a/1190000016496715
Spring相關:https://blog.csdn.net/u010882791/article/details/83756717