maven-assembly-plugin:如何使用appendAssemblyId

lan*_*oxx 21 java maven maven-assembly-plugin

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

  • 主要工件是一个jar库,其他一些模块将依赖于它.
  • 一个执行一些辅助函数的可执行jar文件.没有其他模块依赖于此,它仅供用户在某些情况下手动运行.

这是我用来配置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>
Run Code Online (Sandbox Code Playgroud)

我正在设置appendAssemblyId,false因为否则-jar-with-dependencies将附加到最终名称,我不认为有必要.省略它可以提供更清晰,更易于使用的文件名.

当我跑步时,mvn integration-test我收到以下警告:

[警告]配置选项:'appendAssemblyId'设置为false,并且缺少'classifier'.它不会附加汇编文件:[...]/target/helper-5.0.0-SNAPSHOT.jar,而是成为主项目工件的文件.

注意:如果为此项目提供了多个描述符或描述符格式,则此文件的值将是不确定的!

[警告]用程序集文件替换预先存在的项目主工件文件:[...]/target/my.module-5.0.0-SNAPSHOT.jar:[...]/target/helper-5.0.0- SNAPSHOT.jar

有两件事激怒了我:

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

  2. 为什么有关更换工件的警告出现?

  3. 似乎classifier已弃用为什么警告要求我使用它?

Tun*_*aki 35

那是因为你错误地解释了这些警告.


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

重要的是要记住这个工件附加到项目中:当项目安装(使用mvn install),部署(使用mvn deploy)或释放(使用maven-release-plugin)时,此术语非常有用.附加意味着在项目实施时将安装/部署/发布此工件.并非Maven构建期间生成的所有文件(基本上,target文件夹下的所有内容)都是; 只有附加的文件.因此,您可以很好地创建大量文件,target但只有一个已安装的工件.

除了这个主要工件外,您可能希望构建生成其他工件以进行安装或部署.这是附加或辅助附加工件的概念.主要的例子是Javadoc或源代码:通常在项目发布时,其Javadoc及其来源也是如此.而那就是这个概念classifier开始的地方.

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


我们现在回到你的例子.您的Maven项目是jar打包的,默认情况下会生成一个名为的主要JAR工件my.module-5.0.0-SNAPSHOT.jar; 仍然默认情况下,此主JAR附加到项目(并准备安装/部署).现在你正在配置maven-assembly-plugin创建一个新的JAR工件(被调用,helper-5.0.0-SNAPSHOT.jar但它确实无关紧要).默认情况下,程序集插件会将项目生成的工件附加到项目中.所以你最终会得到2个附件

  1. 具有相同的工件ID my.module; 文件target夹中磁盘上的文件命名helper为1 的事实是无关紧要的,只有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>
Run Code Online (Sandbox Code Playgroud)

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


最后注意:是的,classifier不推荐使用Assembly Plugin 的参数,因为您应该只使用程序集ID作为分类器.

  • Tunaki,非常感谢您的解释.他们真的帮助我了解最新情况.我现在意识到,如果我将`attach`设置为`false`,那么警告就会消失,我会得到所需的结果,但这也意味着不会安装工件.所以我还有两个问题:1.我是否应该避免将`appendAssemblyId`设置为false,而是使用生成的文件名?你会建议我不使用`finalName`属性吗?我原来的意图只是为可执行jar提供一个更加用户友好的名称,我不应该这样做吗? (3认同)