我们说有一个jar main.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?
答案 0 :(得分:1)
翻转四分之一,这是你得到的那个。最有可能的是,它将按字母顺序排在最高位置,因此在您的情况下,它是dep1.jar中的一个。这些文件都有相同的类路径(foo.Bar),虽然这应该看起来抛出一个编译时异常,但它不会因为它只是打包两个jar而不是尝试编译/查看(这个特定的文件)文件因为它是一个.txt文件。
答案 1 :(得分:1)
您不会期望编译时异常,因为资源加载是运行时进程。
您无法在代码中指定资源来自哪个jar,这是一个常见问题,尤其是当有人将类似log4j.properties的内容捆绑到jar文件中时。
您可以做的是在类路径中指定jar的顺序,它将从列表中的第一个中获取资源。这本身就很棘手,因为当你使用像常春藤或maven这样的类路径依赖时,你无法控制类路径中的顺序(无论如何在eclipse插件中)。
唯一可靠的解决方案是将资源调用不同的东西,或将它们放在不同的包中。
答案 2 :(得分:1)
你得到的是未定义的。但是,您可以使用
Resource[] barResource = ctx.getResources("classpath*:foo/bar.txt");
让他们(全部)。 URL
中的Resource
会告诉您他们所在的jar
(虽然我不建议您根据该信息开始编程)。
答案 3 :(得分:0)
规范说明了类路径上的第一个类/资源(AFAIK)。
但我会尝试:
Dep1Class.class.getResource("/foo/bar.txt");
Dep2Class.class.getResource("/foo/bar.txt");
由于Class.getResource工作不能从另一个jar获取资源,而不是系统类加载器。
运气好的话,你不需要和ClassLoader
一起玩,并且需要一个不同的类加载器加载dep2.jar。
答案 4 :(得分:0)
正如@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());
}
}