java.util.Properties 是處理鍵值對配置檔的標準類別,支援 .properties 格式(ISO-8859-1 編碼)。但直接使用 API 需手動管理資源流、異常處理、路徑解析。本文提供一個生產級 PropertiesUtil 封裝,涵蓋檔案載入、讀寫、Servlet/JSP 整合、預設值支援等實戰功能。
| 方法 | 用途 |
|---|---|
PropertiesUtil(String fileName) | 建構子:載入指定路徑的 properties 檔 |
getValue(String key) | 取得屬性值,不存在回傳 null |
getValue(String key, String defaultValue) | 取得屬性值,不存在回傳預設值 |
setValue(String key, String value) | 設定屬性值(記憶體中),需呼叫 saveFile 持久化 |
deleteValue(String key) | 移除屬性 |
list() | 列印所有屬性到 System.out(除錯用) |
saveFile() | 存回原建構子指定檔案 |
saveFile(String fileName, String description) | 存至指定檔案,可加註解標頭 |
getConfigFile(HttpServlet, String) | 靜態方法:從 Web 應用根目錄解析配置檔絕對路徑 |
getConfigFile(PageContext, String) | 靜態方法:JSP 專用,從 PageContext 解析路徑 |
public PropertiesUtil(String fileName) {
this.fileName = fileName;
File file = new File(fileName);
try {
in = new FileInputStream(file);
p = new Properties();
p.load(in); // 載入檔案內容
in.close(); // 立即關閉輸入流
} catch (FileNotFoundException e) {
System.err.println("配置檔案找不到!!"); e.printStackTrace();
} catch (Exception e) {
System.err.println("讀取配置檔案錯誤!!"); e.printStackTrace();
}
}
設計重點:
FileNotFoundException 與通用 Exception 分開處理,錯誤訊息更精確FileInputStream,避免檔案鎖定// Servlet 版本
public static String getConfigFile(HttpServlet hs, String configFileName) {
ServletContext sc = hs.getServletContext();
String configFile = sc.getRealPath("/" + configFileName);
if (configFile == null || configFile.equals("")) {
configFile = "/" + configFileName; // 回退相對路徑
}
return configFile;
}
// JSP 版本 (PageContext 繼承自 ServletContext)
public static String getConfigFile(PageContext pc, String configFileName) {
ServletContext sc = pc.getServletContext();
String configFile = sc.getRealPath("/" + configFileName);
if (configFile == null || configFile.equals("")) {
configFile = "/" + configFileName;
}
return configFile;
}
使用範例:
// 在 Servlet 中
PropertiesUtil util = new PropertiesUtil(PropertiesUtil.getConfigFile(this, "config.properties"));
String dbUrl = util.getValue("jdbc.url");
// 在 JSP 中
<% PropertiesUtil util = new PropertiesUtil(PropertiesUtil.getConfigFile(pageContext, "config.properties")); %>
public void saveFile(String fileName, String description) throws Exception {
try {
File f = new File(fileName);
out = new FileOutputStream(f);
p.store(out, description); // Properties 原生儲存方法
out.close();
} catch (IOException ex) {
throw new Exception("無法儲存指定的配置檔案:" + fileName, ex); // 保留原始堆疊
}
}
優化建議:生產環境建議採用「寫入暫存檔 → rename 覆蓋」模式,確保併發安全與原子性。
# config.properties
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:ORCL
jdbc.username=scott
jdbc.password=tiger
pool.min=5
pool.max=20
PropertiesUtil config = new PropertiesUtil(PropertiesUtil.getConfigFile(this, "config.properties"));
String url = config.getValue("jdbc.url");
int maxPool = Integer.parseInt(config.getValue("pool.max", "20")); // 預設值防呆
// 讀取目前值
String currentLevel = config.getValue("log.level", "INFO");
// 修改並持久化
config.setValue("log.level", "DEBUG");
config.saveFile(); // 寫回原檔案
// 開發/測試/生產環境分別維護 config-dev.properties, config-test.properties, config-prod.properties
// 啟動時透過系統屬性或環境變數決定載入哪個
String env = System.getProperty("app.env", "dev");
PropertiesUtil config = new PropertiesUtil(PropertiesUtil.getConfigFile(this, "config-" + env + ".properties"));
Properties.load(InputStream) 預設使用 ISO-8859-1。中文需透過 native2ascii 工具轉 Unicode 轉義序列(如 \u4e2d\u6587),或改用 XML 格式 Properties.loadFromXML(InputStream)(UTF-8)。
public class ConfigManager {
private static PropertiesUtil instance;
public static synchronized PropertiesUtil getInstance(String configFile) {
if (instance == null) instance = new PropertiesUtil(configFile);
return instance;
}
}
避免重複 I/O,應用啟動時載入一次,運行期快取。
密碼、API Key 等敏感屬性不應明文儲存。建議:
getValue 時自動解密| 方案 | 優點 | 缺點 |
|---|---|---|
| Properties + PropertiesUtil | 零依賴、JDK 內建、輕量 | 型別轉換手動、無巢狀結構、編碼限制 |
| Apache Commons Configuration | 支援多格式、型別轉換、重新載入監聽 | 額外依賴、API 複雜 |
| Spring @ConfigurationProperties | 型別安全、驗證、鬆散綁定、YAML 支援 | 需 Spring 環境 |
| HOCON / Typesafe Config | 人類可讀、合併覆蓋、環境變數替換 | 額外依賴、學習曲線 |
PropertiesUtil 以約 200 行程式碼封裝了配置檔的完整生命週期管理,是中小型專案、舊系統維護、無 Spring 環境下的實用選擇。理解其核心機制(資源管理、路徑解析、異常處理),能幫助開發者快速建立穩健的配置存取層。隨著專案規模增長,建議平滑遷移至 Spring Boot 配置機制或專業配置中心,獲得型別安全、動態重載、加密支援等企業級能力。