我们需要使用Maven构建一个jar,它包含所有依赖项,但是所有这些依赖项都被重命名(重定位)。
假设我们自己的包都以com.mycompagny.projectx.*
开头。我们希望项目依赖项将其包重命名为“embedded
”,而不是我们自己的类。
例如,使用maven-shade-plugin,我无法做到这一点:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<createDependencyReducedPom>true</createDependencyReducedPom>
<artifactSet>
<includes>
<include>*.*</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>*</pattern>
<shadedPattern>embedded.</shadedPattern>
<excludes>
<exclude>com.mycompagny.projectx.*</exclude>
</excludes>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
此处<pattern>*</pattern>
无效。此外,如果我使用<pattern></pattern>
(空字符串),那么所有内容都将重新定位到“嵌入式”软件包,甚至资源(“META-INF”目录)!当然,我们希望资源留在罐子的根部。
我想我们可以创建多个<relocation>
元素,每个元素对应一个依赖项包,但这需要做很多工作:<relocation>com</relocation>
,<relocation>net</relocation>
,<relocation>javax</relocation>
等等。
如何轻松地重新定位超级jar中的所有依赖项,而不涉及我们自己的类,资源和“META-INF”目录?
答案 0 :(得分:6)
更新:此解决方案无法正常运行,请仔细阅读。
我通过查看maven-shade-plugin
的源代码找到了解决方案!它似乎没有记录在任何地方,但有一个 <rawString>
参数可以添加到<relocation>
元素,因此它考虑了<pattern>
和<shadedPattern>
作为正则表达式模式而不是包/文件名。
然后maven-shade-plugin
代码会使用以下内容:
path.replaceAll(pattern, shadedPattern)
处理这些模式。
示例:
<relocation>
<pattern>^([^/]*\.properties)$</pattern>
<shadedPattern>embedded/$1</shadedPattern>
<rawString>true</rawString>
</relocation>
这是一个虚拟示例,它重定位根目录中的所有.properties文件。使用这种技术,可以准确地控制重新定位的内容以及如何,我非常确定。
这是一个更好的例子,它可以满足我的需要(尽管还有一些测试要做):
<relocation>
<pattern>^(?!(com/mycompagny/|META-INF))(.*/.*)$</pattern>
<shadedPattern>embedded/$2</shadedPattern>
<rawString>true</rawString>
</relocation>
更新:遗憾的是,最后一个模式意味着所有使用的都将被重命名,除了&#34; com.mycompagny&#34;和META-INF文件夹。问题是,java.lang.Object
之类的内容将被重命名!当代码运行时,类似的异常将被抛弃:
java.lang.ClassNotFoundException: embedded.java.lang.Object