2012-05-10 115 views
2

在我的Java項目中我正在使用H2內存數據庫,爲此我需要在初始化我的應用程序時加載JDBC驅動程序。我想/需要加載H2 .jar文件動態的,所以我做到以下幾點:如何訪問位於源文件夾內的jar文件?

String classname = "org.h2.Driver"; 
URL u = new URL("jar:file:libs/h2.jar!/"); 
URLClassLoader ucl = new URLClassLoader(new URL[] { u }); 
Driver d = (Driver) Class.forName(classname, true, ucl).newInstance(); 
DriverManager.registerDriver(new DriverShim(d)); 

當我把H2 .jar文件到超出了我的Java源代碼文件夾中的「庫」文件夾(也就是,在Eclipse中,這個「libs」目錄與「src」文件夾位於同一層),那麼這種方法可以正常工作。然而,不幸的是我必須將這個H2 .jar文件放到源代碼文件夾樹中的一個文件夾中,但是放在主類文件夾下。

例如,我的Java包結構看起來像這樣在Eclipse:

<project>/src/my/app/MyApp.java    // main class of my application 
<project>/src/my/app/sub/package/h2.jar  // how to access this? 
<project>/libs/h2.jar      // loading from here works 

我知道這是愚蠢的,但不幸的是我有這種奇怪的設置工作。但是我不知道:如何編輯我的Java代碼(上面列出)以便使用此設置?

編輯︰這也必須在Eclipse以外的工作,所以添加JAR文件到Eclipse中的Java構建路徑是沒有選擇給我。編輯2:我已經嘗試加載「jar:file:my/app/sub/package/h2.jar!/」,但那不適用於我。

在此先感謝所有有幫助的創意!

親切的問候,馬蒂亞斯

+0

你試過jar嗎:file:my/app/sub/package/h2.jar? – kosa

+0

你描述的「奇怪的設置」是一個非常正常的目錄結構。沒有理由將JAR文件放入您的'src'文件夾中。這聽起來像你在你的類路徑中沒有'h2.jar'。 –

+0

@thinksteep:是的,試過了,但沒有奏效。 – Matthias

回答

2

在一些框架參照文件內部的JAR可以使用classpath:前綴來完成。 我懷疑URLClassLoader本身支持它,但值得一試(例如 classpath:/my/app/sub/package/h2.jar)。 但由於不與URLClassLoader的工作,這裏有其他的方法:

一種方式做到這一點是寫自己的ClassLoader讀取從classpath中的JAR文件(使用的getResourceAsStream),解壓縮它(使用ZipInputStream)到內存(例如字節數組的映射)並從那裏加載類。

另一種稍微簡單的方法是從classpath中讀取JAR文件並將其寫入臨時文件中。然後你可以使用普通的URLClassLoader從它加載類。這有一個缺點,即必須將文件寫入文件,並且在JVM退出(unless using Java 7或更高版本)之前,該文件可能無法刪除。

我使用第二種方法(複製到臨時文件)in one project,雖然我使用它到launch an external process。我會很好奇聽到你爲什麼有這樣的要求。如果只是在一個JAR中包含整個應用程序,那麼有很多簡單的方法可以實現這個目標(Maven Assembly Plugin,Maven Shade Plugin,Jar Jar Links,One-JAR等等)。


不,這不是一門功課,但使用在我的課的在線生成系統我/應用/ *和其他幾類(而不是從我)來自動生成整個解決方案。無論如何,我不能給你更多關於這個系統內部的細節,因爲我不知道它們。至於說,我只是不得不忍受它,這就是爲什麼我問這裏...

聽起來像是你在一個WTF環境(它有一個名字的工作?),因此以下是一些開始對其進行黑客入侵的方法:

瞭解有關您的環境的更多信息,特別是以下絕對文件路徑:保存源文件的目錄,保存生成的.class文件的目錄,和程序運行時的當前工作目錄。

如果您可以在運行時獲得任何類型的程序輸出結果,您可以在應用程序中放入一些調試代碼,您可以使用File.listFiles()來抓取機器的目錄樹。如果只能從編譯時發生的情況得到輸出,那麼在編譯期間通過創建自己的annotation processor(apt是Java 6以來的javac的一部分)來執行自己的代碼也是可能的,儘管我不確定註釋處理器是否必須先單獨編譯。

可以從user.dir系統屬性中讀取工作目錄,並且可以從java.class.path系統屬性(除非使用自定義類加載器)獲取類文件的位置。不能保證源目錄中的JAR文件將被複制到類路徑中,因此您可能需要做一些四處觀看。

然後當你知道JAR文件的文件路徑時,你可以使用new File("path/to/h2.jar").toURI().toURL()得到一個URL,然後你可以傳遞給URLClassLoader。

如果沒有其他工作,請上傳庫的源代碼並將它們與您的項目一起編譯。

從長遠來看,嘗試用一個使用標準構建工具(如Maven)和一個通用CI服務器(如Jenkins)的WTF構建環境進行替換。項目有很多庫依賴項是正常的,所以你不需要繞開構建環境來使用它們。

+0

不幸的是,使用「classpath:」不起作用。我必須使用這個environemtn,因爲它是一種自動的在線構建系統,我只能上傳文件和文件夾,位於我的/ app/* – Matthias

+0

以下,我已經更新了我的答案。你能利用這些技巧了解更多有關環境的知識嗎?環境是否公開,以便我們看看它? –

+0

我想你是對的,那真的是一個WTF環境。我會嘗試與其所有者聯繫並找出所有類文件最終會出現的目錄。另外,也許他可以手動將.jar文件複製到適當的目錄中... – Matthias

相關問題