我很困惑java如何從類加載器的角度看待文件系統。相對於類的Java文件位置
假設我在EAR的APP-INF/lib文件夾中有一個jar文件。這個jar文件包含一個類,它實例化了new File("foo.txt")
。另外,foo.txt位於jar旁邊的APP-INF/lib文件夾中。
然後,我在WAR模塊中使用這個庫。現在,代碼是否仍會找到該文件,或者除了在EAR的根目錄或WAR根目錄中找到該文件?
我很困惑java如何從類加載器的角度看待文件系統。相對於類的Java文件位置
假設我在EAR的APP-INF/lib文件夾中有一個jar文件。這個jar文件包含一個類,它實例化了new File("foo.txt")
。另外,foo.txt位於jar旁邊的APP-INF/lib文件夾中。
然後,我在WAR模塊中使用這個庫。現在,代碼是否仍會找到該文件,或者除了在EAR的根目錄或WAR根目錄中找到該文件?
我敢肯定,該文件需要在WAR的根,因爲在你的jar文件WAR負載從EAR的APP-INF/lib下因此將相對搜索到WAR的文件路徑
這是一個例子它是如何處理在classpath
package main;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class Test {
private Test() {
Class<?> c = this.getClass();
ClassLoader cl = c.getClassLoader();
InputStream[] iss = new InputStream[8];
URL[] urls = new URL[8];
iss[0] = c.getResourceAsStream("/resources/txtFile.txt");
iss[1] = c.getResourceAsStream("resources/txtFile.txt");
iss[2] = c.getResourceAsStream("/txtFile.txt");
iss[3] = c.getResourceAsStream("txtFile.txt");
iss[4] = cl.getResourceAsStream("/resources/txtFile.txt");
iss[5] = cl.getResourceAsStream("resources/txtFile.txt");
iss[6] = cl.getResourceAsStream("/txtFile.txt");
iss[7] = cl.getResourceAsStream("txtFile.txt");
urls[0] = c.getResource("/resources/txtFile.txt");
urls[1] = c.getResource("resources/txtFile.txt");
urls[2] = c.getResource("/txtFile.txt");
urls[3] = c.getResource("txtFile.txt");
urls[4] = cl.getResource("/resources/txtFile.txt");
urls[5] = cl.getResource("resources/txtFile.txt");
urls[6] = cl.getResource("/txtFile.txt");
urls[7] = cl.getResource("txtFile.txt");
for (int i = 0; i < 8; i++)
System.out.println("iss[" + i + "] is "
+ String.valueOf(iss[i] == null));
for (int i = 0; i < 8; i++)
System.out.println("url[" + i + "] is "
+ String.valueOf(urls[i] == null));
}
public static final void main(String[] args) {
new Test();
}
}
打印
iss[0] is false
iss[1] is true
iss[2] is true
iss[3] is true
iss[4] is true
iss[5] is false
iss[6] is true
iss[7] is true
url[0] is false
url[1] is true
url[2] is true
url[3] is true
url[4] is true
url[5] is false
url[6] is true
url[7] is true
裝載_resources_時可能會出現這種情況,但操作系統會特別詢問「File」對象,而不是資源。 –
您是否看過我的文章的頂部?底部只是一些額外的 – Dinh
是的,我讀過它。就OP的問題而言,我相信你的回答是不正確的。只有在資源加載時,類加載器行爲對符合JEE的應用服務器中的_File_加載沒有影響。可以說,OP應該將他的數據文件指定爲資源,而不是「文件」,但他不是。如果我誤解了你寫的內容,我很抱歉。 –
你不能依靠的是能夠在EAR文件部署到訪問任何一個java.io.File
對象。
Java EE服務器不需要「爆炸」文件系統中的部署,許多服務器不需要。一些供應商可能會提供這樣做的選擇,但總的來說,依靠這種能力並不明智。
此外,使用類加載器完全無法訪問構建到EAR文件中的純文件。
在EAR文件中,如果對象位於EAR/lib jar文件,EJB模塊,RAR模塊或WEB模塊(WAR)中,則只能從類加載器訪問對象。即使那麼有關於哪些模塊可以在其他模塊中看到的規則,如My ear is not able to find ejb module classes
的答案中所述那就是說,您的問題指的是非標準APP-INF/lib
目錄。您需要參考您的供應商文檔來發現啓用的內容。我隱約記得它是WebLogic或WebSphere中EAR/lib機制標準化的前身(2009年的Java EE 5中)。
爲了使你的'新文件(「foo.txt」)'工作,該文件需要在當前工作目錄中。要從類路徑中加載數據,請使用'Classloader#getResourceAsInputStream'。不過,不確定EAR是如何工作的。不同部分的類路徑可能是分開的,不能直接彼此訪問。 – Thilo
確實。在我所知道的所有appservers中,簡單的文件操作獨立於類加載器行爲。類加載器根本不會輸入圖片。所以,正如@Thilo所說的那樣,文件名是相對於appserver進程當前工作目錄解析的,無論如何。一些appservers設置了特定的CWS,有些則不。因此,在可行的情況下,用戶資源加載通常更好,而不是直接加載文件。然後,你必須考慮類加載器行爲,並且關於各類加載器看起來的規則在JEE規範中列出。 –