Maven - 有没有办法轻松创建一个'uber'jar并重新定位所有依赖项?

ele*_*ype 10 java jar maven 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>
Run Code Online (Sandbox Code Playgroud)

<pattern>*</pattern>是无效的.另外,如果我使用<pattern></pattern>(空字符串),那么所有内容都会重新定位到"嵌入式"包,甚至是资源("META-INF"目录)!当然,我们希望资源保留在jar的根部.

我想我们可以创建多个<relocation>要素,一个是依赖的每个包,但是这将是大量的工作:<relocation>com</relocation>,<relocation>net</relocation>,<relocation>javax</relocation>等.

如何轻松地重新定位超级jar中的所有依赖项,而不涉及我们自己的类,资源和"META-INF"目录?

ele*_*ype 6

更新:此解决方案不起作用,请阅读到最后.

我通过查看源代码找到了解决方案maven-shade-plugin!它似乎没有在任何地方记录,但是有一个<rawString>参数可以添加到<relocation>元素中,因此它考虑到<pattern><shadedPattern>作为正则表达式模式而不是包/文件名.

然后maven-shade-plugin代码使用类似的东西:

path.replaceAll(pattern, shadedPattern)
Run Code Online (Sandbox Code Playgroud)

处理这些模式.

示例:

<relocation>
    <pattern>^([^/]*\.properties)$</pattern>
    <shadedPattern>embedded/$1</shadedPattern>
    <rawString>true</rawString>
</relocation>
Run Code Online (Sandbox Code Playgroud)

这是一个虚拟示例,它重定位根目录中的所有.properties文件.使用这种技术,我可以确切地控制重新定位的内容和方式.

这是一个更好的例子,它做了我需要的东西(尽管仍然需要做一些测试):

<relocation>
    <pattern>^(?!(com/mycompagny/|META-INF))(.*/.*)$</pattern>
    <shadedPattern>embedded/$2</shadedPattern>
    <rawString>true</rawString>
</relocation>
Run Code Online (Sandbox Code Playgroud)

更新:遗憾的是,最后一个模式意味着将重命名所有内容,"com.mycompagny"和META-INF文件夹除外.问题是,java.lang.Object将重命名的事情!当代码运行时,会抛出这样的异常:

java.lang.ClassNotFoundException: embedded.java.lang.Object
Run Code Online (Sandbox Code Playgroud)