11

我目前有一个用 Maven 构建的 Java 测试库,并作为 jar 分发。我的项目依赖于一个非常常见的库(Objectweb ASM),并且我遇到了一些问题,即早期且不兼容的 ASM 版本已经在类路径中。因此,我开始使用jarjar-maven-plugin创建 jar,在内部重新打包 ASM,使其不会与其他版本的 ASM 冲突。

这执行得很好,我的库可以毫无问题地作为依赖项引入。

然而,因为我的项目在 ASM 上有编译范围的依赖,所以每当一个客户端项目添加我的库时,传递依赖也都被引入。因此,假设他们使用特定版本的 ASM,并且他们还将我所依赖的版本添加到类路径中,他们的行为未定义。我想避免这种情况,并允许客户依赖 JarJar'd 工件,而不会让 Maven 不必要地和潜在地危险地拉下传递依赖项。

如何创建用户可以依赖的 JarJar'd 工件而不拉取传递依赖?

4

3 回答 3

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>

此配置的重要部分是:

  • shadedArtifactAttached当设置为 false 时,意味着阴影 jar 将替换通常会生成的主要工件。这默认为 false,但值得指出。
  • createDependencyReducedPom which when set to true means that when the shaded jar is deployed or installed, the pom.xml which is deployed will not include the compile-scope dependencies which have been repackaged into the jar.
  • relocation these elements configure how files within the dependencies are repackaged into the shaded jar. In the above example any class whose canonical name begins with org.objectweb.asm will be moved to ${package.base}.org.objectweb.asm, and thus when packaged in the jar will have the equivalent file path within the jar.

With this configuration, when my project is deployed, when clients declare a compile-scope dependency on my project, it only pulls in the shaded jar, and no transitive dependencies.

于 2011-04-20T08:53:49.923 回答
1

考虑改用 maven-shade-plugin,它允许各种精细控制。

于 2011-04-20T02:24:23.007 回答
0

也许设置<optional>属性将适用于您的情况。在您的 java 测试库 pom.xml 中指定类似以下内容的内容。

  <dependencies>
    <dependency>
      <groupId>asm.group</groupId>
      <artifactId>asm</artifactId>
      <version>x.y</version>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
于 2011-04-20T02:00:29.180 回答