本文為霍格沃茲測試學院優秀學員學習筆記。
在日常自動化測試開發工作中,經常要使用配置檔案,進行環境配置,或進行資料驅動等。我們常常把這些檔案放置在
resources
目錄下,然後通過
getResource
、
ClassLoader.getResource
和
getResourceAsStream()
等方法去讀取。經常看到有不少同學在讀取配置檔案時踩坑,本人也是一路踩坑摸索過來,這裡做一個簡要梳理,供大家參考。
一、何為 classpath ?
讀取資源檔案最關鍵的就是找到檔案的位置,歸根結底就是找路徑,而怎麼找,在哪找就是個問題。這其中和
classpath
有很大關系,是以我們先了解下
classpath
的概念,幫助理清思路。
我們用 Java 編寫的檔案都是
.java
檔案,而想要運作,還需将其編譯成
.class
位元組碼檔案才可被 JVM 運作;這就需要 JVM 先找到對應的
.class
才行,這也就是要找到對應的
classpath
。
JVM 會在編譯項目時,會主動将
.java
檔案編譯成
.class
檔案 并和
resources
目錄下的靜态檔案一起放在
target/classes
(如果是 test 下的類,便會放于
/target/test-classes
下)目錄下;
現有工程目錄如下:

編譯後進入
target
目錄下檢視如下:
二、class.getResource()
先來看
getResource
的用法
先分别執行如下測試代碼,列印
帶有"/"
不帶"/"
的
path
import org.junit.jupiter.api.Test;
public class ResourceTestDemo {
@Test
void getResourceTest(){
System.out.println(ResourceTestDemo.class.getResource(""));
System.out.println(ResourceTestDemo.class.getResource("/"));
}
列印結果:
file:/Users/username/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/test-classes/resourcetest/
file:/Users/username/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/test-classes/
結果分析:
1、
getResource("")
不帶"/“時候是從目前類所在包路徑去擷取資源;
2、
getResource("/")
帶”/"時候是從
classpath
的根路徑擷取;
現在來嘗試擷取
resources
下的檔案
2.txt
3.txt
:
測試代碼:
@Test
void getResourceFileTest(){
System.out.println(ResourceTestDemo.class.getResource("/3.txt"));
System.out.println(ResourceTestDemo.class.getResource("/test/2.txt"));
}
file:/Users/username/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/classes/3.txt
file:/Users/username/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/classes/test/2.txt
三、getClassLoader().getResource()
和上述一樣,先分别執行測試代碼,列印
帶有"/"
不帶"/"
path
:
@Test
void getClassLoaderResourceTest(){
System.out.println(ResourceTestDemo.class.getClassLoader().getResource(""));
System.out.println(ResourceTestDemo.class.getClassLoader().getResource("/"));
}
file:/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/test-classes/
null
getClassLoader().getResource("")
不帶"/“時候是從
classpath
getClassLoader().getResource("/")
帶有”/"列印為
null
,路徑中
無法帶有"/"
現在繼續嘗試擷取
resources
2.txt
3.txt
@Test
void getClassLoaderResourceFileTest(){
System.out.println(ResourceTestDemo.class.getClassLoader().getResource("3.txt"));
System.out.println(ResourceTestDemo.class.getClassLoader().getResource("test/2.txt"));
}
file:/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/classes/3.txt
file:/Users/qinzhen/Documents/TestDev/MyTraining/XUnit/ResourceTest/target/classes/test/2.txt
四、getResourceAsStream()
getResourceAsStream()
方法僅僅是擷取對應路徑檔案的輸入流,在路徑的用法上與
getResource()
一緻。
補充
其實當我們檢視
class.getResource
的源碼時發現如下:
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);
}
其實這裡也是調用了
getClassLoader
,隻是友善了我們使用而已。
總結
class.getResource()
不帶"/"時候是從目前類所在包路徑去擷取資源;
class.getResource()
帶"/"時候是從
classpath
class.getResource()
本質上也是調用了
getClassLoader
,隻是封裝了一層友善了我們使用而已;
getClassLoader().getResource("")
不帶"/"時候是從
classpath
getClassLoader().getResource("/")
路徑中
無法帶有"/"
;
getResourceAsStream()
getResource()
一緻;
以上,供大家探讨。