2010-05-12 100 views
50

我遇到麻煩時,我的Web應用程序所依賴的一個罐子試圖從jar中加載屬性文件。這是jar中的代碼。在JAR中加載屬性文件?

static 
{ 
    Properties props = new Properties(); 
    try 
    { 
     props.load(ClassLoader.getSystemResourceAsStream("someProps.properties")); 
    } catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
    someProperty = props.getProperty("someKey"); 
} 

屬性文件位於Maven項目的「src/main/resources」目錄中。當我在Eclipse的junit測試中運行這段代碼時,它執行得很好。當使用Maven將項目構建到jar中,並將其作爲依賴項包含在我的webb應用程序中時,它無法找到屬性文件。我知道屬性文件位於依賴於jar的基礎目錄,我不知道如何解決這個問題。

請幫忙!

回答

65

問題是,您正在使用getSystemResourceAsStream。只需使用getResourceAsStream即可。從系統類加載器加載系統資源,這幾乎不是當您的jar作爲webapp運行時加載到的類加載器。

它在Eclipse中起作用,因爲啓動應用程序時,系統類加載器會使用您的jar作爲其類路徑的一部分進行配置。 (例如,java -jar my.jar會將my.jar加載到系統類加載器中。)Web應用程序並不是這種情況 - 應用程序服務器使用複雜的類加載將應用程序彼此和應用程序服務器的內部隔離。例如,請參見tomcat classloader how-to以及使用的類加載器層次結構圖。編輯:通常,您將調用getClass()。getResourceAsStream()來檢索類路徑中的資源,但是當您在靜態初始化程序中獲取資源時,您需要顯式地命名該類中的類類加載器,你想從中加載。最簡單的方法是使用包含靜態初始化程序的類,例如

[public] class MyClass { 
    static 
    { 
    ... 
    props.load(MyClass.class.getResourceAsStream("/someProps.properties")); 
    } 
} 
+1

此外,使用線程的上下文類加載器在'Thread.currentThread()getContextClassloader()' – 2010-05-12 01:15:16

+0

@binilŤ小費的小費。我從來不需要這樣做 - 何時需要? – mdma 2010-05-12 01:25:10

+1

@binil - 我已經研究了這一點,並且理解上下文classloader用於當您想離開classloader的層次結構並使用不是您的類加載器的祖先之一的類加載器時。上下文類加載器在這裏不是必需的,因爲資源在同一個webapp中,因此和MyClass在同一個類加載器中。 – mdma 2010-05-12 11:52:09

13

根據記錄,這是記錄在How do I add resources to my JAR?(單元測試說明,但同樣適用於「常規」資源):

將資源添加到類路徑 單元測試,除了將 放置資源的目錄爲 ${basedir}/src/test/resources之外,您遵循與您將資源 添加到JAR的操作相同的 模式。在 這一點上,你將有一個看起來 類似以下的項目 目錄結構:

my-app 
|-- pom.xml 
`-- src 
    |-- main 
    | |-- java 
    | | `-- com 
    | |  `-- mycompany 
    | |   `-- app 
    | |    `-- App.java 
    | `-- resources 
    |  `-- META-INF 
    |   |-- application.properties 
    `-- test 
     |-- java 
     | `-- com 
     |  `-- mycompany 
     |   `-- app 
     |    `-- AppTest.java 
     `-- resources 
      `-- test.properties 

在單元測試中,你可以使用一個簡單的 代碼片段像下面這樣 訪問所需資源 測試:

... 

// Retrieve resource 
InputStream is = getClass().getResourceAsStream("/test.properties"); 

// Do something with the resource 

... 
+0

是一個標準結構,在'test'和'main'中有資源嗎?這只是一個maven約定,或者是JAR文檔本身的一部分? – Thufir 2017-08-18 13:13:41