maven-assembly-plugin:如何使用 appendAssemblyId

maven-assembly-plugin: How to use appendAssemblyId

我有一个多模块 Maven 项目,在一个模块中我想在构建期间创建两个工件:

这是我用来配置 maven-assembly-plugin 插件的代码:

<plugin>
    <artifactId>
        maven-assembly-plugin
    </artifactId>
    <version>2.4</version>
    <executions>
      <execution>
        <id>dist-assembly</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>

        <configuration>
          <finalName>bso</finalName>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <finalName>helper-${project.version}</finalName>
          <appendAssemblyId>false</appendAssemblyId>
          <archive>
            <manifest>
              <mainClass>HelperMain<mainClass>
            </manifest>
          </archive>
        </configuration>

      </execution>
    </executions>
  </plugin>

我将 appendAssemblyId 设置为 false,否则 -jar-with-dependencies 将附加到最终名称,我认为没有必要。省略它会使文件名更清晰、更易于使用。

当我 运行 mvn integration-test 然后我收到以下警告:

[WARNING] Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing. Instead of attaching the assembly file: [...]/target/helper-5.0.0-SNAPSHOT.jar, it will become the file for main project artifact.

NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!

[WARNING] Replacing pre-existing project main-artifact file: [...]/target/my.module-5.0.0-SNAPSHOT.jar with assembly file: [...]/target/helper-5.0.0-SNAPSHOT.jar

有两件事让我很生气:

  1. 尽管警告声称它将用 helper-5.0.0-SNAPSHOT.jar 替换 my.module-5.0.0-SNAPSHOT.jar 但它不会实际上这样做,当构建完成时,两个文件的大小仍然不同。

  2. 为什么会出现更换神器的警告?

  3. 好像classifier已经弃用了为什么警告要我使用它?

那是因为你误解了警告。


让我们回顾一下。默认情况下,非 pom 类型的 Maven 项目将始终生成所谓的主工件。对于 JAR,此工件是将编译后的源代码打包到 JAR 中的结果;对于 WAR,它是构建网络应用程序的结果。

要记住的重要一点是,此工件 附加 到项目:此术语在项目安装(使用 mvn install)、部署(使用 mvn deploy) 或发布(使用 maven-release-plugin)。 Attached表示这个工件会在项目运行时安装/部署/发布。并非所有在 Maven 构建期间生成的文件(基本上,target 文件夹下的所有文件)都是;只有附加的文件。因此,您可以很好地在 target 下创建大量文件,但只有一个已安装的工件。

除了这个主要工件,您可能希望您的构建生成其他工件以进行安装或部署。这就是附加或次要附加工件的概念。主要示例是 Javadoc 或源代码:通常在发布项目时,它的 Javadoc 和源代码也会发布。这就是 the notion classifier kicks in.

在 Maven 存储库中,每个文件都必须遵循相同的命名约定:artifactId-version(-classifier).type。每个次要工件都将具有与主要工件相同的 GAV(组 ID、工件 ID、版本),因此如果您想在 Maven 存储库中放入 1 个主要工件和 1 个附加工件(就像主 JAR 的情况一样)及其 JAR Javadoc 和 JAR 源),您需要一些方法来区分它们。 classifier 的用途是:区分次要工件和主要工件。


现在让我们回到您的示例。您的 jar 打包的 Maven 项目将默认生成一个名为 my.module-5.0.0-SNAPSHOT.jar 的主 JAR 工件;默认情况下,这个主 JAR 仍然附加到项目(并准备好安装/部署)。现在您正在配置 maven-assembly-plugin 以创建一个新的 JAR 工件(称为 helper-5.0.0-SNAPSHOT.jar 但它真的无关紧要)。 Assembly 插件,默认情况下,attaches to the project the artifact it produces。所以你最终得到了 2 个附加的工件

  1. 具有与 my.module 相同的工件 ID; target 文件夹中磁盘上的文件被命名为 helper 的事实是无关紧要的,只有 GAV 坐标才重要
  2. 具有相同版本的5.0.0-SNAPSHOT
  3. 具有与 JAR 相同的包装

并且没有分类器来区分它们。这就是引发警告的原因:您最终将一个次要工件附加到项目,该次要工件有效地替换了主要工件,仅仅是因为它具有相同的坐标。所以结果是:

  1. 两个文件在 target 内的磁盘上具有不同的名称,但这无关紧要,因为
  2. 两者共享相同的坐标,因此只有 1 个幸存。

是Assembly Plugin产生的那个会在冲突中获胜,并替换掉附属的主神器

如果您想说服自己相信所有这些,请在项目上 运行 mvn clean install 并检查您的本地存储库。您会注意到只会安装 jar-with-dependencies 工件。另一个(主要神器)发出了噗声。

你也可以配置一个<distributionManagement>:

<distributionManagement>
    <repository>
        <id>local-repo-test</id>
        <url>file://...</url>
    </repository>
</distributionManagement>

并调用 mvn clean deploy。然后您可以检查唯一部署的工件将是 jar-with-dependencies.


最后说明:是的,Assembly 插件的 classifier 参数已弃用,因为您应该只使用程序集 ID 作为分类器。