如何从类路径中的不同jar加载一个相同的命名资源?

时间:2014-08-15 15:20:20

标签: java spring jar embedded-resource

我们说有一个jar main.jar依赖于另外两个罐子 - dep1.jardep2.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?

5 个答案:

答案 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());
        }
    }