| 方法 | 路徑以 / 開頭 | 路徑不以 / 開頭 |
|---|---|---|
Class.getResource(path) | 從 ClassPath 根目錄 查找 | 從 當前類所在包目錄 查找(相對路徑) |
ClassLoader.getResource(path) | 不允許以 / 開頭(返回 null) | 從 ClassPath 根目錄 查找(絕對路徑) |
package testpackage;
public class TestMain {
public static void main(String[] args) {
// 當前類所在包目錄
System.out.println(TestMain.class.getResource(""));
// ClassPath 根目錄
System.out.println(TestMain.class.getResource("/"));
}
}
輸出(Eclipse 環境):
file:/E:/workspace/Test/bin/testpackage/
file:/E:/workspace/Test/bin/
假設項目結構:
bin/
├── 1.properties ← ClassPath 根
├── testpackage/
│ ├── TestMain.class
│ ├── 2.properties ← 同包資源
│ └── subpackage/
│ └── 3.properties ← 子包資源
// 同包資源:相對路徑
TestMain.class.getResource("2.properties")
// → file:/E:/workspace/Test/bin/testpackage/2.properties
// 子包資源:相對路徑 + 子目錄
TestMain.class.getResource("subpackage/3.properties")
// → file:/E:/workspace/Test/bin/testpackage/subpackage/3.properties
// 根目錄資源:絕對路徑
TestMain.class.getResource("/1.properties")
// → file:/E:/workspace/Test/bin/1.properties
同理適用:Class.getResourceAsStream() 路徑規則完全一致。
TestMain t = new TestMain();
System.out.println(t.getClass().getClassLoader().getResource(""));
System.out.println(t.getClass().getClassLoader().getResource("/")); // null
System.out.println(t.getClass().getClassLoader().getResource("1.properties"));
System.out.println(t.getClass().getClassLoader().getResource("testpackage/2.properties"));
輸出:
file:/E:/workspace/Test/bin/
null
file:/E:/workspace/Test/bin/1.properties
file:/E:/workspace/Test/bin/testpackage/2.properties
TestMain.class.getResource("/") == t.getClass().getClassLoader().getResource("")
即:Class 絕對路徑 = ClassLoader 相對路徑,都指向 ClassPath 根。
getResourceAsStream()兩者的 AsStream 版本路徑解析邏輯與上述完全一致。
| 錯誤寫法 | 後果 | 修正 |
|---|---|---|
clazz.getResource("/config.xml") 但文件在包內 | 找不到資源(去根目錄找了) | 去掉 / 或改用 clazz.getResource("config.xml") |
clazz.getClassLoader().getResource("/config.xml") | 返回 null | 去掉 /:clazz.getClassLoader().getResource("config.xml") |
Spring 中 classpath:config.xml vs classpath*:config.xml | 前者只取第一個,後者合併所有 JAR 中同名資源 | 多模塊/多 JAR 共存時用 classpath*: |
Class.getResource(\"relative/path\"),框架/工具代碼用 ClassLoader.getResource(\"absolute/path\")」。URL 確認實際解析路徑,特別是打包成 JAR/War 後。file:/E:/xxx,破壞可移植性。src/main/resources 下的文件編譯輸出至 ClassPath 根,包結構對應子目錄。徹底搞清這兩組 API 的路徑語義,能消除 90% 的「開發環境正常、打包部署找不到配置文件」的經典疑難雜症。