Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从类路径中的不同JAR加载相同的命名资源之一?_Java_Spring_Jar_Embedded Resource - Fatal编程技术网

Java 如何从类路径中的不同JAR加载相同的命名资源之一?

Java 如何从类路径中的不同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

假设有一个jar
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”)
很危险;也许是因为类加载器。