無論普通 Java 專案還是 Web 專案,**類載入器** 是讀取 classpath (src 編譯後的 classes 目錄) 資源的標準方式。本文匯總三種最常用、最穩健的寫法。
InputStream in = ThisClass.class.getClassLoader().getResourceAsStream("aa.properties");
// 或
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("aa.properties");
適用:獨立應用、單元測試、Web 容器 (Context ClassLoader 通常指向 WebAppClassLoader)。
// 相對路徑 (同包目錄)
InputStream in = ThisClass.class.getResourceAsStream("aa.properties");
// 絕對路徑 (從 classpath 根)
InputStream in = ThisClass.class.getResourceAsStream("/aa.properties");
// 子包資源
InputStream in = ThisClass.class.getResourceAsStream("/com/pkg/aa.properties");
**關鍵差異**:帶 / 開頭 = 從 classpath 根查找;不帶 = 從當前類所在包查找。
// 基礎用法 (檔案名不含 .properties)
ResourceBundle rb = ResourceBundle.getBundle("aa"); // 根包
ResourceBundle rb = ResourceBundle.getBundle("com.pkg.aa"); // 子包
String val = rb.getString("key");
優點:自動處理 _zh_TW 等 Locale 變體、內建快取、型別安全獲取字串。
public static Properties loadProps(String path) {
Properties p = new Properties();
InputStream in = null;
try {
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
if (in == null) in = ClassUtils.class.getClassLoader().getResourceAsStream(path);
if (in == null) throw new IllegalArgumentException("資源未找到: " + path);
p.load(in);
return p;
} catch (IOException e) {
throw new RuntimeException("載入失敗: " + path, e);
} finally { IOUtils.closeQuietly(in); }
}
URL url = ThisClass.class.getResource("/"); // classpath 根
if (url == null) url = Thread.currentThread().getContextClassLoader().getResource("/");
File classesRoot = new File(url.toURI()); // .../target/classes 或 .../WEB-INF/classes
File projectRoot = classesRoot.getParentFile().getParentFile(); // 專案根