我们需要使用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”目录也是如此)!当然,我们希望资源停留在 jar 的根部。我猜我们可以创建多个
<relocation>
元素,每个依赖项包一个,但是这将需要大量工作:<relocation>com</relocation>
,<relocation>net</relocation>
,<relocation>javax</relocation>
等。关于如何在不影响我们自己的类,资源和“META-INF”目录的情况下轻松地在uber jar中重新定位所有依赖项的想法?
最佳答案
更新:此解决方案实际上并不起作用,请仔细阅读。
通过查看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>
更新:可悲的是,最后一个模式意味着所有使用的东西都将被重命名,除了“com.mycompagny”和META-INF文件夹。问题是,像
java.lang.Object
这样的东西将被重命名!当代码运行时,将抛出诸如此类的异常:java.lang.ClassNotFoundException: embedded.java.lang.Object