天天看點

Java Resource資源path載入解惑

一、問題引入

最近使用如下方式載入配置檔案時總是傳回

null

Thread.currentThread().getContextClassLoader().getResource("config.properties")

配置檔案說明:

config.properties

檔案放置在與

src

目錄同級的

config

目錄中。

二、問題分析

檢視API文檔發現關于類ClassLoader方法

getResource

的傳回值有如下描述:

讀取資源的 URL 對象;如果找不到該資源,或者調用者沒有足夠的權限擷取該資源,則傳回 null。

由文檔API可知,傳回null有兩種原因引起:

  1. 找不到該資源;
  2. 對該資源沒有擷取權限。

這裡顯然可以排除第2中原因,那麼明明config/config.properties檔案存在,為什麼會找不到呢?

原因和Java Resource資源載入路徑有關。

預設情況下,Java在載入資源時,隻會在工程的

classpath

下尋找。

這裡需要說明的是對classpath的認識不要局限在隻是在這裡尋找二進制class檔案、jar包,Java還會在這裡尋找文本檔案(例如配置檔案),圖像,聲音資源等。

為了一探究竟,我們列印出classpath,可以通過如下兩種方式:

  1. 擷取屬性

    java.class.path

    :
    System.getProperty("java.class.path")
               
  2. 利用如下代碼段:
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        //Get the URLs
        URL[] paths = ((URLClassLoader)sysClassLoader).getURLs();
        for(int i=; i< paths.length; i++)
        {
            System.out.println(paths[i].getFile());
        }
               

以上兩種方式,得到的

classpath

結果相同:

/Users/zq/Documents/workspace/yourProjectName/bin/
/Users/zq/Documents/workspace/yourProjectName/lib/ant.jar
/Users/zq/Documents/workspace/yourProjectName/lib/commons-logging-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/log4j-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/mysql-connector-java--bin.jar
/Users/zq/Documents/workspace/yourProjectName/lib/httpclient-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/httpcore-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/commons-codec-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/commons-lang-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/mail-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/trove-a6.jar
           

其中可以看出

classpath

中并沒有包含

config/config.properties

三、問題解決

到目前為止,問題的原因已經搞清楚了,那麼問題的解決也就迎刃而解了:

隻要把

config/config.properties

添加到工程的

build path

中即可。

再次列印出

classpath

,可以看到最後一行已經包含了

config

目錄:

······
/Users/zq/Documents/workspace/yourProjectName/lib/commons-lang-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/mail-.jar
/Users/zq/Documents/workspace/yourProjectName/lib/trove-a6.jar
/Users/zq/work_xxx/yourProjectName/config/
           

四、深入探究

在Java工程中,擷取資源一般通過如下兩種方式(相應的getResourceAsStream方法傳回的是同一資源的流形式inputstream):

  1. Class.getResource()
  2. ClassLoader.getResource()
    ClassLoader的擷取:
    1. Thread.currentThread().getContextClassLoader()
    2. clazz.getClassLoader()
    3. ClassLoader. getSystemClassLoader()
               

兩者的差別為:第一種方式在相對clazz的路徑中尋找資源;第二種方式是在整個classpath中尋找資源。

兩者的共同點為:都在

classpath

中尋找資源。

最後需要說明的是:

Java中不存在标準的相對路徑,各種相對路徑取資源的方式都是基于某種規則轉化為絕對路勁,但是在程式設計過程中,絕對不要直接使用絕對路徑。

是以,我們在使用Java載入Resource資源時,隻要尋找到合适的參考基點,就能很輕松得定位你要找的resource資源,一般情況下參考基點有如下幾種:

  1. classpath:

    本博文已經詳細的做了介紹,這裡不再做贅述。

  2. 目前工程目錄(強烈不推薦使用,會帶來移植問題)
    System.getProperty("user.dir")
               
  3. Web應用程式的根目錄

    在Web應用程式中,一般通過

    ServletContext.getRealPath("/" )

    方法得到Web應用程式的根目錄的絕對路徑。

五、參考連結:

http://blog.csdn.net/cutesource/article/details/6141768

http://blog.csdn.net/ak913/article/details/7399056