2017-10-05 92 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中)。