如何使用Maven创建一个JarJar'd工件,其中工件的使用不会提取传递依赖?

Gru*_*eck 11 software-distribution classpath artifact jarjar maven

我目前有一个Java测试库,它是用Maven构建的,并以jar形式发布.我的项目依赖于一个非常常见的库(Objectweb ASM),并且我遇到过类似路径中已经存在早期且不兼容的ASM版本的问题.因此,我开始使用jarjar-maven-plugin来创建jar,在内部重新打包ASM,它不会与另一个版本的ASM冲突.

这执行得很好,我的库可以作为依赖项拉入,没有问题.

但是,因为我的项目在ASM上具有编译范围依赖性,所以每当客户端项目添加我的库时,传递依赖关系也都被拉入.因此,假设,如果他们使用特定版本的ASM,并且他们还将我依赖的版本添加到类路径中,则它们具有未定义的行为.我想避免这种情况,并允许客户端依赖JarJar'd工件,而不会让Maven不必要地和可能危险地降低传递依赖性.

如何创建一个JarJar'd工件,用户可以依赖它而不会提取传递依赖关系?

Gru*_*eck 17

我通过抛弃jarjar-maven-plugin并恢复到maven-shade-plugin找到了解决这个问题的方法.这允许在您自己的命名空间内重新打包类,设置jar的主类,最重要的是,重写生成的pom以包括现在捆绑的编译时依赖项.

我的pom.xml中实现此目的的部分是:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>

            <shadedArtifactAttached>false</shadedArtifactAttached>
            <createDependencyReducedPom>true</createDependencyReducedPom>

            <relocations>
                <relocation>
                    <pattern>org.objectweb.asm</pattern>
                    <shadedPattern>${repackage.base}.org.objectweb.asm</shadedPattern>
                </relocation>
            </relocations>
            <transformers>
                <transformer
                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>${package.base}.my.MainClass</mainClass>
                </transformer>
            </transformers>
        </configuration>
    </execution>
</executions>
Run Code Online (Sandbox Code Playgroud)

此配置的重要部分是:

  • shadedArtifactAttached当设置为false时,表示阴影jar将替换通常会生成的主要工件.这默认为false,但值得指出.
  • createDependencyReducedPom 当设置为true时,表示当部署或安装着色jar时,部署的pom.xml将不包含已重新打包到jar中的编译范围依赖项.
  • relocation这些元素配置依赖项中的文件如何重新打包到着色jar中.在上面的示例中,任何以规范名称开头的类org.objectweb.asm都将被移动到${package.base}.org.objectweb.asm,因此当打包在jar中时,jar中将具有等效的文件路径.

使用此配置,当我的项目部署时,当客户端声明我的项目的编译范围依赖项时,它只会拉入阴影jar,并且没有传递依赖项.