如何避免库罐中的资源冲突? [英] How to avoid resource collisions in library jars?

查看:142
本文介绍了如何避免库罐中的资源冲突?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很担心当库 Foo Bar 时,每个人都会暴露类路径上的资源相同的名称,在此示例中说 properties.txt

I'm worried about the situation when libraries Foo and Bar each expose a resource on the classpath with the same name, say properties.txt in this example.

假设设置了Maven并且 jars 与Maven一起部署,如果我有这个设置:

Assuming a Maven set up and the jars are deployed with Maven, if I have this set up:

Library Foo:

Library Foo:

$ cat Foo/src/main/resources/properties.txt
$ Foo

和图书馆栏:

$ cat Bar/src/main/resources/properties.txt
$ Bar

以及 App 取决于它们,其 pom 看起来像这样 - 简而言之,这只是说构建一个带依赖的jar,依赖于 Foo Bar

And an App that depends on them, whose pom looks something like this - in a nutshell this just says "build a jar-with-dependencies, and depend on Foo and Bar:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>bundle-project-sources</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <archive>
          <manifest>
            <mainClass>me.unroll.deptest.App</mainClass>
            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
          </manifest>
          <manifestEntries>
            <Implementation-Build>${buildNumber}</Implementation-Build>
          </manifestEntries>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </execution>
  </executions>
</plugin>

问题是它真的好像是 properties.txt 文件被破坏了。让我们尝试 jar tf

Problem is it really seems like the properties.txt file was clobbered. Let's try a jar tf:

unrollme-dev-dan:target Dan$ jar tf App-1.0-SNAPSHOT-jar-with-dependencies.jar 
META-INF/
META-INF/MANIFEST.MF
properties.txt
META-INF/maven/
META-INF/maven/me.unroll.deptest/
META-INF/maven/me.unroll.deptest/Bar/
META-INF/maven/me.unroll.deptest/Bar/pom.xml
META-INF/maven/me.unroll.deptest/Bar/pom.properties
META-INF/maven/me.unroll.deptest/Foo/
META-INF/maven/me.unroll.deptest/Foo/pom.xml
META-INF/maven/me.unroll.deptest/Foo/pom.properties
me/
me/unroll/
me/unroll/deptest/
me/unroll/deptest/App.class

所以我在 App 中运行了一个 main 类:

So I ran a main class in App that does:

try (InputStream is = App.class.getClassLoader().getResourceAsStream("properties.txt")) {

    java.util.Scanner s = new java.util.Scanner(is);
        System.out.println("Scanner: " + s.next());

}

输出为:

unrollme-dev-dan:target Dan$ java -jar App-1.0-SNAPSHOT-jar-with-dependencies.jar 
Scanner: Bar

哎呀,Bar赢了。 mvn package -ing App 时没有警告或错误。运行时可能没有选择错误文件时出现警告或错误,实际上它无声地失败。

Whoops, Bar won. No warnings or errors when mvn package-ing App. No warnings or errors when running that the wrong file may have been chosen, in fact it failed silently.

所以我想要求正确的做法来避免这种情况。一,这样的事情应该大声失败,而不是轻轻地失败。第二,我能想到的唯一解决方案是所有资源文件都应该像Java开发中的其他所有资源一样正确打包,即库永远不会在code> properties.txt 中暴露全球命名空间;它应该出现在像 me / unroll / deptest / foo 这样的文件夹中,就像其他一切一样。我持怀疑态度,因为我没有看到任何实际上这样做的Maven示例。那么这里的最佳做法是什么?

So I want to ask proper practice to avoid this. One, something like this should fail loudly, not softly. Two, the only solution I can think is that all resource files should be properly packaged like everything else in Java development, i.e., a library should never expose properties.txt in the "global" namespace; it should appear in a folder like me/unroll/deptest/foo just like everything else. I'm skeptical because I haven't seen any Maven example that actually does this. So what is best practice here?

推荐答案

你在 Java 中做了什么来避免碰撞库?套餐!这是已建立并且易于理解的方法。包也适用于资源:

And what do you do in Java to avoid collisions between libraries? Packages! This is established and well understood approach. Packages work with resources as well:

com/example/foo/Foo.class
com/example/foo/properties.txt

和第二个库:

com/example/bar/Bar.class
com/example/bar/properties.txt

请注意, properties.txt 位于不同的包中,因此位于最终JAR中。实际上这种方法是首选,因为用于检索此类资源的API变得更容易:

Note that properties.txt lies in different packages and thus directories in final JAR. Actually this approach is preferred because the API for retrieving such resources becomes easier:

App.class.getResourceAsStream("properties.txt"))

vs。

Bar.class.getResourceAsStream("properties.txt"))

It只是工作,因为 Class.getResourceAsStream()默认是本地的基础类包。当然,当你在 Foo Bar 的实例方法中时,你只需说 getClass ().getResourceAsStream( 的properties.txt)。此外,您仍然可以轻松引用这两个文件,就像您引用类一样:

It just works because Class.getResourceAsStream() is by default local to package of underlying class. Of course when you are inside an instance method of either Foo or Bar you simply say getClass().getResourceAsStream("properties.txt"). Moreover you can still reference both files easily, just like you reference classes:

getClass().getResourceAsStream("/com/example/foo/properties.txt");
getClass().getResourceAsStream("/com/example/bar/properties.txt");








我是持怀疑态度,因为我没有看到任何实际上这样做的Maven示例。

I'm skeptical because I haven't seen any Maven example that actually does this.

真实世界的例子:你有一个名为的com集成测试com.example.foo.FooTest 。默认情况下,Spring期望上下文文件位于: /src/test/resources/com/example/foo/FooTest-context.xml

Real world example: you have a Spring integration test named com.example.foo.FooTest. By default Spring expects the context file to reside under: /src/test/resources/com/example/foo/FooTest-context.xml.

这篇关于如何避免库罐中的资源冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆