Java 如何从类路径中的不同JAR加载相同的命名资源之一?
假设有一个jarJava 如何从类路径中的不同JAR加载相同的命名资源之一?,java,spring,jar,embedded-resource,Java,Spring,Jar,Embedded Resource,假设有一个jarmain.jar,它依赖于另外两个jar-dep1.jar和dep2.jar。这两个依赖项都位于main.jar的MANIFEST.MF的类路径中。每个依赖项jar内部都有一个目录foo,其中包含一个文件bar.txt: dep1.jar | \--foo/ | \--bar.txt dep2.jar | \--foo/ | \--bar.txt 下面是main.jar的一个主要类: public class App { public stat
main.jar
,它依赖于另外两个jar-dep1.jar
和dep2.jar
。这两个依赖项都位于main.jar的MANIFEST.MF的类路径中。每个依赖项jar内部都有一个目录foo
,其中包含一个文件bar.txt
:
dep1.jar
|
\--foo/
|
\--bar.txt
dep2.jar
|
\--foo/
|
\--bar.txt
下面是main.jar的一个主要类:
public class App
{
public static void main( String[] args ) {
ApplicationContext ctx = new StaticApplicationContext();
Resource barResource = ctx.getResource("classpath:foo/bar.txt");
}
}
将加载两个bar.txt
文件中的哪一个?有没有一种方法可以在资源URL中指定文件应该从哪个jar加载?翻转四分之一,这就是您将得到的。最有可能的是,它将是按字母顺序排列的最高的一个,因此在您的示例中是dep1.jar中的一个。这两个文件都有相同的类路径(foo.Bar),虽然这看起来会引发编译时异常,但不会,因为它只会打包两个JAR,而不会尝试编译/查看(此特定文件)文件,因为它是一个.txt文件。您不会期望编译时异常,因为资源加载是一个运行时过程
您无法在代码中指定资源将来自哪个jar,这是一个常见的问题,特别是当有人将log4j.properties之类的东西捆绑到jar文件中时
您可以做的是指定类路径中JAR的顺序,它将从列表中的第一个JAR中提取资源。这本身就很棘手,因为当您使用ivy或maven之类的东西作为类路径依赖项时,您无法控制类路径中的顺序(无论如何,在eclipse插件中)
唯一可靠的解决方案是调用不同的资源,或者将它们放在不同的包中。规范规定,类路径上的第一个类/资源被占用(AFAIK)
不过,我会尝试:
Dep1Class.class.getResource("/foo/bar.txt");
Dep2Class.class.getResource("/foo/bar.txt");
与系统类加载器相反,As Class.getResource works无法从另一个jar获取资源
幸运的是,您不需要使用ClassLoader
s,而是使用不同的类加载器loade dep2.jar。您得到的是未定义的类加载器。但是,您可以使用
Resource[] barResource = ctx.getResources("classpath*:foo/bar.txt");
把他们两个(全部)都弄到手。Resource
中的URL
将告诉您它们在哪个jar
中(尽管我不建议您根据这些信息开始编程)。正如@Sotirios所说,您可以使用ctx.getResources(…)
获得同名的所有资源,代码如下:
ApplicationContext ctx = new StaticApplicationContext();
Resource[] resources = ctx.getResources("classpath*:/foo/bar.txt");
for (Resource resource : resources) {
System.out.println("resource file: " + resource.getURL());
InputStream is = new FileInputStream(resource.getFile());
if (is == null) {
System.out.println("resource is null");
System.exit(-1);
}
Scanner scanner = new Scanner(is);
while(scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
@Jenson两个类:bar.txt
不是一个类,因此不会有任何冲突。这不是真的。对具有绝对路径(开头的斜杠)的类调用的.getResource()会查看类路径的根。将选择第一个内部结构为/foo/bar.txt的.jar。@cobby谢谢,这似乎是我很久以前就有的误解。可能是因为getClass().getResource(“foo.txt”)
很危险;也许是因为类加载器。