設計模式選擇:為什麼用 ResourceBundle?
| 方案 | 優點 | 缺點 | 適用場景 |
| ResourceBundle | JDK 內建、自動快取、支援國際化、屬性檔自動發現 | 僅支援 ISO-8859-1 編碼(需配合 native2ascii) | 簡單配置、國際化專案、無額外依賴 |
| Properties + 輸入流 | 支援 UTF-8 直接讀取、靈活控制重載 | 需手動管理快取與線程安全 | 需 UTF-8、動態重載、複雜配置 |
| Spring @Value/@ConfigurationProperties | 類型安全、自動轉換、SpEL 支援、熱重載 | 依賴 Spring 容器、啟動較慢 | Spring Boot 專案、複雜配置綁定 |
完整實作代碼
package com.example.config;
import java.util.ResourceBundle;
/**
* Properties 配置文件處理工具類
* 採用單例模式 + 雙重檢查鎖定,線程安全、延遲初始化
*/
public class ConfigHolder {
private static volatile ResourceBundle bundle;
private static final String CONFIG_BASE_NAME = "config"; // classpath:config.properties
/**
* 私有構造器防止實例化
*/
private ConfigHolder() {}
/**
* 延遲初始化載入配置
* 雙重檢查鎖定確保高併發下單次初始化
*/
private static void loadConfig() {
if (bundle == null) {
synchronized (ConfigHolder.class) {
if (bundle == null) {
// 支援包路徑:如 "com.example.config.app" 對應 classpath:com/example/config/app.properties
bundle = ResourceBundle.getBundle(CONFIG_BASE_NAME);
}
}
}
}
/**
* 獲取指定鍵的配置值
* @param key 配置鍵
* @return 配置值,鍵不存在拋出 MissingResourceException
*/
public static String getValue(String key) {
loadConfig();
return bundle.getString(key);
}
/**
* 安全獲取配置值(帶預設值)
* @param key 配置鍵
* @param defaultValue 預設值
* @return 配置值或預設值
*/
public static String getValue(String key, String defaultValue) {
try {
return getValue(key);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 獲取整數配置
* @param key 配置鍵
* @param defaultValue 預設值
* @return 解析後的整數
*/
public static int getInt(String key, int defaultValue) {
String value = getValue(key, String.valueOf(defaultValue));
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* 獲取布林配置
* @param key 配置鍵
* @param defaultValue 預設值
* @return 解析後的布林值
*/
public static boolean getBoolean(String key, boolean defaultValue) {
String value = getValue(key, String.valueOf(defaultValue));
return Boolean.parseBoolean(value);
}
/**
* 強制重新載入配置(支援動態更新)
*/
public static void reload() {
bundle = null;
loadConfig();
}
}
配置文件規範與放置
標準放置位置
src/main/resources/
├── config.properties # 基礎配置(必要)
├── config_zh_TW.properties # 繁體中文(可選)
├── config_en_US.properties # 英文(可選)
└── config-dev.properties # 開發環境(透過 JVM 參數切換)
配置文件內容範例
# 資料庫配置
db.url=jdbc:mysql://localhost:3306/myapp?useUnicode=true&characterEncoding=utf8
db.username=root
db.password=secret
db.pool.size=20
# Redis 配置
redis.host=127.0.0.1
redis.port=6379
redis.timeout=3000
# 業務配置
app.page.size=20
app.cache.enabled=true
app.upload.max.size=10485760
進階用法與擴展
多環境配置切換
// JVM 啟動參數指定配置基礎名
// -Dconfig.base=config-dev
public class ConfigHolder {
private static final String CONFIG_BASE_NAME =
System.getProperty("config.base", "config");
// ...
}
整合 Spring Environment(推薦 Spring 專案)
@Component
public class SpringConfigHolder {
@Autowired
private Environment env;
public String getValue(String key) {
return env.getProperty(key);
}
public String getValue(String key, String defaultValue) {
return env.getProperty(key, defaultValue);
}
}
熱重載支援(配合 Spring Cloud Config / Nacos)
@RefreshScope
@Component
public class DynamicConfigHolder {
@Value("${app.cache.enabled:true}")
private boolean cacheEnabled;
// 配置中心推送變更自動更新
}
最佳實踐總結
- 命名規範:採用 `<模塊>.<功能>.<屬性>` 格式(如 `db.pool.size`、`app.upload.max.size`)
- 敏感資訊:密碼、密鑰等敏感配置嚴禁明文存儲,需加密或使用配置中心秘密管理
- 類型轉換:工具類提供
getInt、getBoolean 等類型安全方法,避免手動解析錯誤
- 預設值策略:業務關鍵配置必須提供合理預設值,防止配置遺漏導致啟動失敗
- 文檔化:配置文件添加註釋說明用途、可選值、影響範圍