原文同步發表至個人博客【夜月歸途】 原文鏈接:http://www.guitu18.com/se/java/2019-02-22/29.html 作者:夜月歸途 出處:http://www.guitu18.com/ 本博客中未標明轉載的文章歸作者夜月歸途和博客園所有。 歡迎轉載,但未經作者同意必須保 ...
原文同步發表至個人博客【夜月歸途】
原文鏈接:http://www.guitu18.com/se/java/2019-02-22/29.html
作者:夜月歸途出處:http://www.guitu18.com/
本博客中未標明轉載的文章歸作者夜月歸途和博客園所有。 歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
在Java中經常會需要讀取各種各樣的配置文件,在獲取資源時,一般會用到 Class.getResource()
或 ClassLoader.getResource()
;
那麼這兩種方式在獲取資源文件時有什麼相同或者不同的地方呢?
先貼上代碼目錄結構:
┌─src
│ └─main
│ └─java
│ └─com.guitu18.blog
│ ├─classpath
│ │ └─GetResourceTest.java
│ └─SpringbootApplication.java
└─resource
├─mapper
│ └─BlogDao.xml
└─confog.properties
Class.getResource()
測試代碼,先看 this.getClass().getResource()
:
代碼的輸出結果我直接貼在代碼的上一行了,下同。
@Test
public void classGetResource() {
// file:/E:/repo/guitu-blog/target/test-classes/com/guitu18/blog/classpath/
System.out.println(this.getClass().getResource(""));
// file:/E:/repo/guitu-blog/target/test-classes/
System.out.println(this.getClass().getResource("/"));
}
可以看出,getResource("")
獲取的是當前類所在包的路徑,而 getResource("/")
獲取的是 classpath
根路徑;
繼續測試,我們獲取目錄下的文件:
@Test
public void classGetProperties() {
// file:/E:/repo/guitu-blog/target/classes/config.properties
System.out.println(this.getClass().getResource("/config.properties"));
// null
System.out.println(this.getClass().getResource("BlogDao.xml"));
// file:/E:/repo/guitu-blog/target/classes/mapper/BlogDao.xml
System.out.println(this.getClass().getResource("/mapper/BlogDao.xml"));
/**
* .java文件在編譯後編程.class,所以這裡參數傳的文件名是.class結尾
*/
// file:/E:/repo/guitu-blog/target/classes/com/guitu18/blog/classpath/GetResourceTest.class
System.out.println(this.getClass().getResource("GetResourceTest.class"));
// file:/E:/repo/guitu-blog/target/classes/com/guitu18/blog/SpringbootApplication.class
System.out.println(this.getClass().getResource("../SpringbootApplication.class"));
// file:/E:/repo/guitu-blog/target/classes/com/guitu18/blog/classpath/GetResourceTest.class
System.out.println(this.getClass().getResource("../classpath/GetResourceTest.class"));
}
輸出結果顯示:
- 當以
"/"
開頭時,是從classpath
路徑開始匹配資源; - 當不以
"/"
開頭時,是從當前類所在包的路徑開始匹配資源; - 兩種方式都可以通過
"/"
或"../"
在文件夾上下層路徑切換;
另外,在獲取文件時,我們還可以通過 getResourceAsStream
直接獲取文件輸入流,如:
InputStream inputStream = this.getClass().getResourceAsStream("/config.properties");
且 getResourceAsStream()
和 getResource()
在獲取文件流和文件路徑時,路徑選擇機制是一樣的。
ClassLoader.getResource()
接著看 this.getClass().getClassLoader().getResource
,上代碼:
@Test
public void classLoaderGetResource() {
// file:/E:/repo/guitu-blog/target/test-classes/
System.out.println(this.getClass().getClassLoader().getResource(""));
// null
System.out.println(this.getClass().getClassLoader().getResource("/"));
}
在使用 ClassLoader().getResource
獲取路徑時,不能以 "/"
開頭,且路徑總是從 classpath
根路徑開始;
@Test
public void classLoaderGetProperties() {
/**
* 同樣可以通過"/"或"../"在文件夾上下層路徑切換
*/
// file:/E:/repo/guitu-blog/target/classes/config.properties
System.out.println(this.getClass().getClassLoader().getResource("config.properties"));
// null
System.out.println(this.getClass().getClassLoader().getResource("BlogDao.xml"));
// file:/E:/repo/guitu-blog/target/classes/mapper/BlogDao.xml
System.out.println(this.getClass().getClassLoader().getResource("mapper/BlogDao.xml"));
/**
* 同Class.getResourceAsStream()一樣,我們還可以通過ClassLoader.getResourceAsStream()直接獲取文件輸入流
* ClassLoader.getResourceAsStream()和ClassLoader.getResource()在獲取文件流和文件路徑時,路徑選擇機制也是一樣的
*/
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties");
}
這裡跟上面差別不大,所以直接把結果寫在代碼註釋中了, ClassLoader().getResource
只能從 classpath
開始獲取資源,同樣也能使用getResourceAsStream()
獲取文件輸入流,且路徑機制一樣;
總結
Class.getResource()
可以從當前Class
所在包的路徑開始匹配獲取資源,也可以從classpath
根路徑開始匹配獲取資源;ClassLoader().getResource()
只能從classpath
根路徑開始匹配獲取資源;Class.getResource()
從當前包所在路徑獲取資源時不能以"/"
開頭,而從classpath
根路徑獲取資源時必須以"/"
開頭;ClassLoader().getResource()
不能以"/"
開頭,且路徑總是從classpath
根路徑開始;- 它們都能通過
getResourceAsStream()
方法獲取對應路徑文件的輸入流,文件路徑匹配機制和其getResource()
方法一樣;