java當前路徑和相對路徑相關的疑惑
原文:https://blog.csdn.net/haoyifen/article/details/52733371
讓人迷惑的相對路徑
Java 中有一個很容易讓人誤解的問題, 就是路徑問題.
我們來看一段程式碼.
專案路徑為 /home/pathExample, 類的全限定名是 org.haoyifen.PathTest, 類的絕對地址為 /home/pathExample/src/main/java/org/haoyifen/PathTest.java
public class PathTest {
@Test
public void relativePath () {
Path path = Paths.get("books.xml");
Path absolutePath = path.toAbsolutePath();
System.out.println(absolutePath);
}
}
初學者可能以為上面輸出的 * /home/pathExample/src/main/java/org/haoyifen/books.xml* , 但其實輸出的是 * /home/pathExample/books.xml* , 也就是相對於專案目錄.
這說明 Java 類中處理相對路徑並不是以當前該類的路徑來進行相對的, 這一點不同於 HTML 中的 js 檔案和 CSS 檔案的引用.
原因
其實 Java 中處理相對路徑是以 JDK 執行時的屬性”user.dir” 來進行相對的. 我們可以改變”user.dir” 對應的值, 來改變相對路徑轉換為絕對路徑的值.
@Test
public void changeUserDir() {
//將user.dir對應的值設定為/home/haoyifen
System.setProperty("user.dir", "/home/haoyifen");
Path absolutePath = Paths. get("books.xml").toAbsolutePath();
//驗證相對路徑轉換為絕對路徑時, 是以user.dir來進行計算的
Assert.assertEquals(absolutePath, Paths.get("/home/haoyifen/books.xml"));
}
在不同的執行環境中, 比如開發時的 IDE, 執行時的命令列或者 WEB 容器, JDK 執行時的屬性”user.dir” 的值的改變規則都是不同的, Java 中絕對不要使用相對路徑來讀取檔案, 否則會出現開發時是正常的, 執行時就提示 java.io.FileNotFoundException: books.xml (沒有那個檔案或目錄)
類路徑和類載入器
Java中載入檔案, 最好是使用類路徑來進行載入, 以下是類路徑的一些規則 (假設類的全限定名為org.haoyifen.PathTest, 類的根路徑為/home/pathExample/target/classes)
- PathTest.class.getResource(“”)
當前類所在的目錄,file:/home/pathExample/target/classes/org/haoyifen/ - PathTest.class.getResource(“/”)
類的跟路徑, file:/home/pathExample/target/classes/ - PathTest.class.getClassLoader().getResource(“”)
類的跟路徑, file:/home/pathExample/target/classes/ - Thread.currentThread().getContextClassLoader().getResource(“”)
同上, 類的跟路徑, file:/home/pathExample/target/classes/
Spring 框架中的解決辦法
Spring 不僅僅適用於 Java SE, 也適用於 Java EE, Spring 中有個很重要的概念就是 Resource 介面, Resource 是一個抽象於底層實現的資源描述符, 用於獲取底層資源 (可以是檔案系統的 File 也可以是網路 URL) 的輸入流和其他相關資訊. 其中使用的最多的實現就是 ClassPathResource, 常見的使用案例有:
- ClassPathXmlApplicationContext 載入 xml 配置檔案啟動 Spring 框架
- Mybatis-Spring 中載入 Class 路徑中的 mapper.xml 檔案來生成 DAO
Resource 最重要的方法如下:
*/
@Override
public InputStream getInputStream() throws IOException {
InputStream is;
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
}
else if (this.classLoader != null) {
is = this.classLoader.getResourceAsStream(this.path);
}
else {
is = ClassLoader.getSystemResourceAsStream(this.path);
}
if (is == null) {
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
}
return is;
}
使用的就是 classLoader 來進行載入資源.
總結
- Java 中相對路徑是以 System.getProperty(“user.dir”) 來進行相對的.
- Java 中絕對不要使用相對路徑來載入檔案, user.dir 設定規則在 IDE, 命令列和 WEB 容器中是不同的.
- 使用類路徑或者類載入器來載入檔案, 這在 Java SE 專案和 WEB 容器中表現都是統一的.