配置默认 Mojo 执行的指南

在大多数需要配置插件的情况下,有两个选项可以很好地工作:插件级配置和执行级配置。插件级配置是配置将从命令行使用的插件的最常用方法,被定义为默认生命周期的一部分,或者在所有调用中使用通用配置。事实上,对于从命令行直接调用,插件级配置一直是历史上唯一的选择。

另一方面,如果更高级的构建过程需要从使用不同配置的单个插件执行 mojos(有时是相同的 mojos,有时是不同的 mojos),则最常用的是执行级别配置。这些情况通常涉及作为标准构建过程的一部分引入的插件,但这些插件不存在于该特定包装的默认生命周期映射中。在这些情况下,执行之间共享的公共设置通常仍然在插件级配置中指定。

但是,这两个选项遗漏了一些重要的配置用例:

  • 当 CLI 驱动的调用需要自己的配置时,Mojos 从命令行和构建期间运行。
  • Mojo 执行绑定到生命周期,作为特定打包的默认映射的一部分,尤其是在需要将相同的 mojo 添加到具有不同配置的第二个执行的情况下。
  • 来自同一插件的 mojo 组,作为特定包装的默认映射的一部分绑定到生命周期,但需要单独的配置。

executionId隐含执行的默认值

当您考虑到上述配置用例适用于 POM 中未明确提及的 mojo 时,将它们称为隐含执行是合理的。但是,如果它们是隐含的,那么 Maven 如何允许用户为它们提供配置呢?我们实施的解决方案相当简单且技术含量低,但对于处理高级用例来说应该绰绰有余。从 Maven 2.2.0 开始,从命令行直接调用的每个 mojo 都将default-cli分配一个执行 ID,这将允许使用此默认执行 ID 从 POM 配置该执行。同样,通过指定 POM 打包的默认生命周期映射绑定到构建生命周期的每个 mojo 将具有执行 IDdefault-<goalName>分配给它,以允许独立配置每个默认 mojo 执行。

示例:程序集插件的命令行变体调用

考虑用户想要assembly:assembly直接在命令行上执行 mojo,但已经有assembly:single在主构建生命周期中运行的 mojo 的配置的情况。由于这些配置需要不同的选项,因此用户不能使用插件级配置部分来指定通用元素。

在这种情况下,程序集插件配置可能如下所示:

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <tarLongFileMode>gnu</tarLongFileMode>    
  </configuration>
  <executions>
    <execution>
      <id>build-distros</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <descriptors>
          <descriptor>src/main/assembly/bin.xml</descriptor>
          <descriptor>src/main/assembly/src.xml</descriptor>
        </descriptors>
      </configuration>
    </execution>
    <execution>
      <id>default-cli</id>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
          <descriptorRef>project</descriptorRef>
        </descriptorRefs>
      </configuration>
    </execution>
  </executions>
</plugin>

在上面的例子中,你可以看到几个有趣的事情。首先,主构建过程将在构建阶段调用assembly:singlemojo package,并使用项目中包含的自定义程序集描述符生成二进制和源代码分发工件。其次,程序集插件的所有调用都应tarLongFileMode使用gnu. 最后,当从命令行调用程序集插件时,它将为项目构建标准jar-with-dependenciesproject工件,并忽略src/main/assembly.

现在,请注意两个执行块引用程序集描述符的方式不同。一种通过节使用自定义描述符descriptors,另一种通过节使用标准描述符descriptorRefs。这两个部分不能相互覆盖,因此不可能descriptorRefs在插件级配置块中设置一个部分(例如,提供对它的 CLI 访问,因为 Maven 的历史版本需要),然后让build-distros调用覆盖它节中指定的自定义描述符descriptors

示例:配置compile为运行两次

在这种情况下,用户希望为他的打包项目运行compiler:compile两次 mojo 。jar这样做的主要原因是为应用程序提供一个入口点,如果用户使用的是早于 1.5 的 Java 版本,该入口点将警告用户,然后正常退出。如果没有这样的入口点,用户在尝试使用 1.4 或更早版本的 JRE 运行此应用程序时会遇到堆栈跟踪。

因此,用户需要编译他的应用程序的大部分以针对 1.5 Java 规范,然后编译其余的(入口点)以针对较旧的规范……比如 1.3。第一次执行将指定source和的target1.5,并添加一个excludes部分以避免编译应用程序的入口点。然后第二遍将重新指定sourceand targetto 1.3,并且基本上将原来excludes的节反转为includes节,从而编译入口点类。

生成的配置可能如下所示:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.5</source>
    <target>1.5</target>
  </configuration>
  <executions>
    <execution>
      <id>default-compile</id>
      <configuration>
        <excludes>
          <exclude>**/cli/*</exclude>
        </excludes>
      </configuration>
    </execution>
    <execution>
      <id>build-java14-cli</id>
      <phase>compile</phase>
      <goals>
        <goal>compile</goal>
      </goals>
      <configuration>
        <source>1.3</source>
        <target>1.3</target>
        <includes>
          <include>**/cli/*</include>
        </includes>
      </configuration>
    </execution>
  </executions>
</plugin>

在上述编译器插件配置中需要注意三件重要的事情:

  • 默认sourcetarget兼容性级别适用于 Java 1.5。这意味着编译器将从主代码库和测试代码库生成 Java 1.5 的二进制文件,除非另有覆盖。
  • 目标的默认传递compile排除**/cli/*路径模式,但将编译其他所有内容src/main/java以在 Java 1.5 下运行。
  • compilemojo的第二遍- 在调用的执行中 - 将and版本build-java14-cli重置为,并从第一遍反转排除规则。这意味着第二次,编译器将为匹配路径模式的类生成面向 1.4 的二进制文件。sourcetarget1.3**/cli/*

示例:分别配置compiletestCompilemojos

最后,在我们使用编译器插件梳理出这些不同的用例的基础上,考虑用户希望将 Java 规范的 1.4 版作为其运行时平台的情况。但是,他仍然希望在像 TestNG 这样的单元测试框架中找到便利和其他优势。这会强制用户compile使用一组sourcetarget值来配置 mojo - 特别是1.4- 以及testCompile使用另一组 ( 1.5) 来配置 mojo。

生成的编译器插件配置可能如下所示:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <executions>
    <execution>
      <id>default-compile</id>
      <configuration>
        <source>1.3</source>
        <target>1.3</target>
      </configuration>
    </execution>
    <execution>
      <id>default-testCompile</id>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </execution>
  </executions>
</plugin>

这个例子相当简单明了。首先,default-compile执行将sourcetarget值设置1.3为允许较旧的 Java 版本运行项目。然后,default-testCompile执行将sourcetarget值重置为1.5,这使项目能够使用 TestNG 等使用注释的工具。

顺便提一下,上面的例子有点做作。编译器插件默认以 Java 1.3 为目标,因此真正需要的唯一配置是default-testCompile执行。执行default-compile重新指定插件默认值。唯一可能有用的时候是父 POM 定义插件级配置,source并且target需要更改以用于这些不同的编译器执行目的。此示例旨在说明单独配置默认生命周期 mojo 的可能性。