在 Java 專案開發中,配置文件(如 database.properties)的存放位置與讀取方式直接影響部署靈活性與維護性。本文探討將配置文件置於類所在包目錄的優勢,並提供一個健壯的 PropHelper 工具類,支援 JAR、WAR、開發環境等多種部署場景下的自動尋找與讀取。
/----------- 其他包目錄
|
|------- edu.ec.database
|
|--------------- ConnectionPool.java
|--------------- Dao.java
|--------------- DaoFactory.java
|--------------- database.properties ← 與相關類同包
|--------------- RecordSet.java
優點:
target/classes 或打入 JAR/WAR 的對應包路徑。Java 無類似 VB Application 的全域對象提供安裝路徑。但配置文件既在 CLASSPATH 中,即可利用 ClassLoader.getResourceAsStream() 讀取。
支援按優先級自動搜尋:
WEB-INF/classes)。user.dir)。public class PropHelper {
public static InputStream guessPropFile(Class cls, String propFile) {
try {
ClassLoader loader = cls.getClassLoader();
// 1. 包根目錄
InputStream in = loader.getResourceAsStream(propFile);
if (in != null) return in;
// 2. 類所在包目錄
Package pack = cls.getPackage();
if (pack != null) {
String path = packageToPath(pack.getName());
in = loader.getResourceAsStream(path + propFile);
if (in != null) return in;
}
// 3. 用戶目錄
File f = new File(System.getProperty("user.dir"), propFile);
if (f.exists()) return new FileInputStream(f);
// 4. CLASSPATH 所有路徑
String[] cps = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
for (String cp : cps) {
f = new File(cp, propFile);
if (f.exists()) return new FileInputStream(f);
}
return null;
} catch (Exception e) { throw new RuntimeException(e); }
}
private static String packageToPath(String packName) {
return packName.replace('.', '/') + "/";
}
}
public class ConnectionPool {
static {
Properties dbProp = new Properties();
InputStream in = PropHelper.guessPropFile(ConnectionPool.class, "database.properties");
if (in != null) dbProp.load(in);
// 使用 dbProp 配置資料源 (C3P0, HikariCP 等)
}
}
若需在 WEB-INF 等特殊目錄尋找配置,可先解析應用實際部署路徑:
public static String getAppPath(Class cls) {
ClassLoader loader = cls.getClassLoader();
String clsName = cls.getName() + ".class";
Package pack = cls.getPackage();
String path = (pack != null) ? packageToPath(pack.getName()) : "";
URL url = loader.getResource(path + clsName);
String realPath = url.getPath();
// 處理 "file:" 前綴、JAR 內路徑 (!) 等
if (realPath.startsWith("file:")) realPath = realPath.substring(5);
int pos = realPath.indexOf(path + clsName);
realPath = realPath.substring(0, pos - 1);
if (realPath.endsWith("!")) realPath = realPath.substring(0, realPath.lastIndexOf("/"));
return realPath;
}
利用此路徑判斷是否為 Web 環境(含 WEB-INF/classes),再擴展搜尋邏輯。
部署為 JAR 時,建議將配置文件置於 JAR 同級目錄,直接用
new FileInputStream("database.properties")讀取,便於外部修改;WAR 則沿用包內讀取方式。