Maven - 有没有办法轻松创造一个超级' uber' jar重定位的所有依赖项?

时间:2015-01-30 17:49:19

标签: java maven jar maven-shade-plugin

我们需要使用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”目录?

1 个答案:

答案 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