[有圖有真相]IDEA下的Maven工程讀取properties等資源文件的路徑問題


僅供參考,如有錯誤或不足歡迎留言指正。


我們以maven的web項目爲例:
這裏寫圖片描述
接下來我們看看工程結構:這裏只討論src目錄和target目錄
src目錄:

  • src/main/java: java:起初生成maven項目時並沒有這個resource文件夾,是建立maven項目後手動添加進去的,用於存放java源文件
  • src/main/resources:存放項目的各種資源(如圖片文本之類的)及全局配置文件
  • src/main/webapp:webapp目錄是web目錄所特有的目錄,不作詳細介紹

target目錄:
- classes:這個就是classpath目錄,即存放java字節碼文件以及相關配置文件(如properties文件)的根目錄,後面會用代碼演示資源文件的路徑及相關知識
target目錄下的其他目錄不再做介紹,與本文討論的知識並無多大關係。

src 與 target: src/main/下的java文件下的.java文件編譯後的.class文件及resources文件相關資源文件都會在target/classes中。

關於java的字節碼文件存放位置: target/classes目錄下會生成對應的相關字節碼文件及相關的包文件夾
關於src/main/resources文件:這是一個專門存放各類信息文件的配置文件夾,筆者曾犯的一個錯誤就是將配置文件放在了java目錄下,導致始終無法獲取配置文件的輸入流

說完了相關文件介紹,我們進入正題:
首先介紹兩個方法:getResource(String filePath)getResourceAsStream(String filePath)
getResource(String filePath):下面上代碼:
這裏寫圖片描述
分析:通過運行結果我們可以看到通過Class類對象調用getResource(String filePath)方法獲取的路徑是classes文件下的類路徑但不包含類本身;而通過ClassLoader類調用的getResource(String filePath)方法,則輸出到classpath的根目錄。

ok,說到此處,我覺得有上 API文檔的必要了。我們來看看Class和ClassLoader類的getResource(),getResourceAsStream()方法:
Class類的getResource()和getResourceAsStream():
getResource()方法註釋:
<li> If the {@code name} begins with a {@code '/'}
* (<tt>'&#92;u002f'</tt>), then the absolute name of the resource is the
* portion of the {@code name} following the {@code '/'}
* <li> Otherwise, the absolute name is of the following form:
* <blockquote>
* {@code modified_package_name/name}
* </blockquote>
* <p> Where the {@code modified_package_name} is the package name of this object with {@code '/'} substituted for {@code '.'}
* (<tt>'&#92;u002e'</tt>).

大致意思是:如果路徑名(也就是filePath)以 “/” 開頭,那麼資源的絕對路徑名是文件路徑的一部分。否則,其路徑名爲 “包名/文件名”,最後還特別說明了一下:包名的點被 “/”所替代掉。
getResourceAsStream()註釋的資源路徑說明與getResource()方法相同,可以自己區查閱API文檔。

ClassLoader類的getResource()和getResourceAsStream():
getResource()註釋:

* Finds the resource with the given name.  A resource is some data(images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code.
     * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
     * identifies the resource.
     * <p> This method will first search the parent class loader for the
     * resource; if the parent is <tt>null</tt> the path of the class loader
     * built-in to the virtual machine is searched.  That failing, this method
     * will invoke {@link #findResource(String)} to find the resource.  </p>

大致意思是:通過給定的名字搜索資源。這些資源指的是那些可以通過一種不依賴java代碼的方式而被java文件所接收的資源(例如:圖片,音頻,文本等等)。關於搜索規則,其中提到了一個關鍵點:首先搜索父目錄(字節碼目錄classes)。通過這點,我們已經可以知道該方法的filepath開頭是不加”/”的,即從classes目錄開始搜索。而關於getResourceAsStream()的搜索規則,文檔註釋中說與getResource()一樣,在此就不再貼註釋了。

說的再多,不如貼代碼來的直接:
首先在如圖mysql.properties文件位置:
這裏寫圖片描述

同時呢,我們可以在classes下看到相關的文件夾config及mysql.properties文件:
這裏寫圖片描述

前面我們提到過,資源的路徑取的是classpath(即類加載路徑)下的路徑。接下來我們要討論的是分別通過Class及ClassLoader類的getResourceAsStream()方法獲取mysql.properites文件流從而獲取數據。

public class Test {
    public static void main(String[] args) throws Exception {
        getStreamByClass("/config/mysql.properties");
        getStreamByClassLoader("config/mysql.properties");
    }
    public static void getStreamByClass(String filePath) throws Exception {
        //通過Class的getResourceAsStream()獲取properties文件輸入流
        InputStream in = Test.class.getResourceAsStream(filePath);
        //當然,也可以通過實例獲取Class對象
        InputStream in1 = new Test().getClass().getResourceAsStream(filePath);
        printProperties(in);
        printProperties(in1);
    }
    public static void getStreamByClassLoader(String filePath) throws Exception {
        //通過ClassLoader的getResourceAsStream()獲取輸入流
        InputStream in = Test.class.getClassLoader().getResourceAsStream(filePath);
        //同樣的,通過實例也可以獲取ClassLoader對象
        InputStream in1 = new Test().getClass().getClassLoader().getResourceAsStream(filePath);
        printProperties(in);
        printProperties(in1);
    }
    public static void printProperties(InputStream in) throws Exception {
        Properties pro = new Properties();
        pro.load(in);
        System.out.println("url: " + pro.getProperty("url")
                         + "user: " + pro.getProperty("user")
                         + "password: " + pro.getProperty("password"));
    }
}

運行結果如下:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章