關於獲取資源文件,Class.getResource和ClassLoader.getResource的區別

原文同步發表至我的博客【夜月歸途】html

原文連接:http://www.guitu18.com/se/java/2019-02-22/29.htmljava

在Java中常常會須要讀取各類各樣的配置文件,在獲取資源時,通常會用到 Class.getResource()ClassLoader.getResource() ;編程

那麼這兩種方式在獲取資源文件時有什麼相同或者不一樣的地方呢?app

先貼上代碼目錄結構:測試

┌─src
│  └─main
│     └─java
│        └─com.guitu18.blog
│           ├─classpath
│           │  └─GetResourceTest.java
│           └─SpringbootApplication.java
└─resource
   ├─mapper
   │   └─BlogDao.xml
   └─confog.properties

Class.getResource()

測試代碼,先看 this.getClass().getResource()
代碼的輸出結果我直接貼在代碼的上一行了,下同。ui

@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 根路徑;this

繼續測試,咱們獲取目錄下的文件:url

@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"));
}

輸出結果顯示:spa

  1. 當以 "/" 開頭時,是從 classpath 路徑開始匹配資源;
  2. 當不以 "/" 開頭時,是從當前類所在包的路徑開始匹配資源;
  3. 兩種方式均可以經過 "/""../" 在文件夾上下層路徑切換;

另外,在獲取文件時,咱們還能夠經過 getResourceAsStream 直接獲取文件輸入流,如:code

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() 獲取文件輸入流,且路徑機制同樣;

總結

  1. Class.getResource() 能夠從當前 Class 所在包的路徑開始匹配獲取資源,也能夠從 classpath 根路徑開始匹配獲取資源;
  2. ClassLoader().getResource() 只能從 classpath 根路徑開始匹配獲取資源;
  3. Class.getResource() 從當前包所在路徑獲取資源時不能以 "/" 開頭,而從 classpath 根路徑獲取資源時必須以 "/" 開頭;
  4. ClassLoader().getResource() 不能以 "/" 開頭,且路徑老是從 classpath 根路徑開始;
  5. 它們都能經過 getResourceAsStream() 方法獲取對應路徑文件的輸入流,文件路徑匹配機制和其 getResource() 方法同樣;
相關文章
相關標籤/搜索