dje*_*lin 5 java packages dependency-management maven
我很担心库Foo和Bar每个库在类路径上暴露一个具有相同名称的资源时的情况,比如properties.txt在这个例子中.
假设一个Maven设置并且jars部署了Maven,如果我有这个设置:
图书馆Foo:
$ cat Foo/src/main/resources/properties.txt
$ Foo
Run Code Online (Sandbox Code Playgroud)
和图书馆酒吧:
$ cat Bar/src/main/resources/properties.txt
$ Bar
Run Code Online (Sandbox Code Playgroud)
并且App这取决于他们,他们pom看起来是这样的-简而言之,这只是说:"建立一个罐子,有依赖性,并且依赖于Foo和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>
Run Code Online (Sandbox Code Playgroud)
问题是它看起来真的像properties.txt文件被破坏了.我们来试试吧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
Run Code Online (Sandbox Code Playgroud)
所以我跑了一个main课App:
try (InputStream is = App.class.getClassLoader().getResourceAsStream("properties.txt")) {
java.util.Scanner s = new java.util.Scanner(is);
System.out.println("Scanner: " + s.next());
}
Run Code Online (Sandbox Code Playgroud)
输出是:
unrollme-dev-dan:target Dan$ java -jar App-1.0-SNAPSHOT-jar-with-dependencies.jar
Scanner: Bar
Run Code Online (Sandbox Code Playgroud)
哎呀,酒吧赢了.mvn package-ing 时没有警告或错误App.运行时可能没有选择错误文件时出现警告或错误,实际上它无声地失败.
所以我想要求正确的做法来避免这种情况.一,这样的事情应该大声失败,而不是轻声失败.第二,我能想到的唯一解决方案是所有资源文件都应该像Java开发中的其他所有资源一样正确打包,也就是说,库永远不会properties.txt在"全局"命名空间中公开; 它应该出现在me/unroll/deptest/foo像其他一切一样的文件夹中.我持怀疑态度,因为我没有看到任何实际上这样做的Maven示例.那么这里的最佳做法是什么?
在Java中如何避免库之间的冲突?包!这是既定且易于理解的方法。包也可以与资源一起使用:
com/example/foo/Foo.class
com/example/foo/properties.txt
Run Code Online (Sandbox Code Playgroud)
和第二个图书馆:
com/example/bar/Bar.class
com/example/bar/properties.txt
Run Code Online (Sandbox Code Playgroud)
请注意,properties.txt它位于不同的包中,因此位于最终 JAR 中的目录中。实际上,这种方法是首选,因为用于检索此类资源的 API 变得更容易:
App.class.getResourceAsStream("properties.txt"))
Run Code Online (Sandbox Code Playgroud)
与
Bar.class.getResourceAsStream("properties.txt"))
Run Code Online (Sandbox Code Playgroud)
它之所以有效,Class.getResourceAsStream()是因为默认情况下它是底层类包的本地包。当然,当您位于 或 的实例方法内时,Foo您Bar只需说getClass().getResourceAsStream("properties.txt")。此外,您仍然可以轻松引用这两个文件,就像引用类一样:
getClass().getResourceAsStream("/com/example/foo/properties.txt");
getClass().getResourceAsStream("/com/example/bar/properties.txt");
Run Code Online (Sandbox Code Playgroud)
我对此表示怀疑,因为我还没有看到任何真正做到这一点的 Maven 示例。
真实世界的示例:您有一个名为 的 Spring 集成测试com.example.foo.FooTest。默认情况下,Spring 希望上下文文件位于:/src/test/resources/com/example/foo/FooTest-context.xml。
| 归档时间: |
|
| 查看次数: |
1502 次 |
| 最近记录: |