2017-10-05 131 views
1

我很困惑java如何從類加載器的角度看待文件系統。相對於類的Java文件位置

假設我在EAR的APP-INF/lib文件夾中有一個jar文件。這個jar文件包含一個類,它實例化了new File("foo.txt")。另外,foo.txt位於jar旁邊的APP-INF/lib文件夾中。

然後,我在WAR模塊中使用這個庫。現在,代碼是否仍會找到該文件,或者除了在EAR的根目錄或WAR根目錄中找到該文件?

+1

爲了使你的'新文件(「foo.txt」)'工作,該文件需要在當前工作目錄中。要從類路徑中加載數據,請使用'Classloader#getResourceAsInputStream'。不過,不確定EAR是如何工作的。不同部分的類路徑可能是分開的,不能直接彼此訪問。 – Thilo

+2

確實。在我所知道的所有appservers中,簡單的文件操作獨立於類加載器行爲。類加載器根本不會輸入圖片。所以,正如@Thilo所說的那樣,文件名是相對於appserver進程當前工作目錄解析的,無論如何。一些appservers設置了特定的CWS,有些則不。因此,在可行的情況下,用戶資源加載通常更好,而不是直接加載文件。然後,你必須考慮類加載器行爲,並且關於各類加載器看起來的規則在JEE規範中列出。 –

回答

1

我敢肯定,該文件需要在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 
+0

裝載_resources_時可能會出現這種情況,但操作系統會特別詢問「File」對象,而不是資源。 –

+0

您是否看過我的文章的頂部?底部只是一些額外的 – Dinh

+2

是的,我讀過它。就OP的問題而言,我相信你的回答是不正確的。只有在資源加載時,類加載器行爲對符合JEE的應用服務器中的_File_加載沒有影響。可以說,OP應該將他的數據文件指定爲資源,而不是「文件」,但他不是。如果我誤解了你寫的內容,我很抱歉。 –

1

你不能依靠的是能夠在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中)。