2009-11-10 93 views
15

我有一個JAR文件,其中包含應用程序以及該應用程序的配置文件。應用程序從類路徑加載配置文件(使用ClassLoader.getResource()),並且使用烘焙到JAR文件中的配置文件完全滿足其依賴關係。我可以使用類路徑覆蓋正在運行的jar文件嗎?

有時我希望應用程序以稍微不同的配置運行(特別是我想覆蓋JDBC URL以指向不同的數據庫),因此我創建了一個新的配置文件,並將其存儲在正確的目錄結構中這意味着在目錄中的類路徑條目的/config),和我想要做這樣的事情:

java -cp new-config:. -jar application.jar 

但我不能讓classpath中有應用程序JAR的內容之前,new-config路徑條目。難道它是JAR的內容始終是類路徑中的第一件事嗎?

+0

你試過把配置去罐子外,在它自己的jar文件路徑相對於中application.jar (../conf/config.jar)?如果你這樣做,我認爲你可以設置類路徑指向應用程序清單中的配置jar,你可以設置新的配置改變config.jar。我希望我有更多的時間做一個演示來確認我的答案,但我不能......所以我把它寫成了評論 – JuanZe 2009-11-10 15:15:10

+0

你的意思是,而不是在JAR裏面? – Guss 2009-11-11 13:26:22

+0

是的,而不是在應用程序的同一個罐子裏,把配置放在第二個罐子裏...... – JuanZe 2009-11-12 02:41:47

回答

20

爲什麼不直接調用應用程序,而無需指定的罐子,而是明確地命名應用程序的主類?這將允許你以所需的順序將你的new-config和application.jar放在classpath中:

(假設「新配置」是包含重寫屬性文件的目錄)

java -cp new-config:application.jar Application.Main.Class 

我相信主類的名稱,可在罐內的MANIFEST.MF文件中找到....

+2

主要的問題是我實際上並沒有使用-cp參數,而是在清單文件中指定類路徑,因爲應用程序需要許多其他外部JAR - 提取所有這些會相當容易出錯。但我敢打賭,我可以編寫一些腳本,從清單中提取類路徑並自動構建相關的命令行,因此這可能是我將使用的答案。 – Guss 2009-11-11 16:45:06

1

使用CLASSPATH可能無法實現。有幾種方法可以讓撥打ClassLoader.getResource()的電話使用靜態路徑來查找資源。如果是這樣,它將繞過CLASSPATH。

3

由-jar選項指定的JAR存檔將覆蓋所有其他值。

你將不得不通常使用外部配置文件來完成它,或者建立自己的解決方案withod ClassLoader.getResource()

我們使用一個定製的解決方案來解決這個問題 - 我們加載內部屬性,像這樣:

final Properties p = new Properties(); 
p.load(DefaultConfiguration.class.getResourceAsStream("config.properties")); 

我們然後加載以同樣的方式與外部文件,並在外部的覆蓋內部值。

對於信息的類加載的作品怎麼看:

http://java.sun.com/javase/6/docs/technotes/tools/findingclasses.html

+0

這的確是問題。我明白,除了以不同的方式啓動應用程序 - 就像alasdairg所建議的那樣,或者編寫一些自定義加載代碼,沒有任何辦法。謝謝。 – Guss 2009-11-12 13:13:01

13

當您使用-jar選項來啓動應用程序:

... JAR文件是所有 用戶類的源,並其他用戶類路徑 設置被忽略

如所述here。解決方法是在jar文件的清單中指定類路徑以包含附加路徑(描述爲here)。

但是,由於您只是在討論修改配置,您可能需要採取不依賴於類路徑的不同方法。例如,我通常通過Spring使用屬性文件來配置我的應用程序,以確定數據庫的位置等。我的Spring配置在測試,QA和現場環境中是一致的,但是在啓動應用程序時,我將一個不同的屬性文件作爲命令行參數傳遞。

春天配置片段

<bean id="MyDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource"> 
    <property name="url" value="jdbc:microsoft:sqlserver://${dbServer}:${dbPort};DatabaseName=${dbName}"/> 
    <property name="username" value="${dbUserName}"/> 
    <property name="password" value="${dbPassword}"/> 
    <property name="suppressClose" value="false"/> 
</bean> 

屬性文件片段

dbServer=MyServer 
dbPort=1433 
dbName=MyDb 
dbUserName=Me 
dbPassword=foobar 
+0

將配置文件作爲可選參數傳遞是一個好主意,但我的應用程序目前接受很多參數,添加另一個參數會對用戶造成問題。 感謝您的答案。 – Guss 2009-11-11 16:46:54

+0

你如何啓動你的應用程序?我認爲通過Webstart,.bat或.sh腳本等啓動應用程序,傳遞的參數將隱藏給用戶。 – Adamski 2009-11-11 17:05:52

+0

否 - 用戶從命令行自行啓動應用程序,傳遞所需的參數 - 日期,要處理的文件等。 – Guss 2009-11-12 13:11:50