Maven 生命周期和插件详解

Maven 生命周期及其阶段

Maven 基于生命周期的核心概念。有三个内置的生命周期:

  • clean:负责清理项目;
  • default:负责构建项目;
  • site:负责建立项目站点。

每个生命周期都包含一些阶段(phase),用户与 Maven 最直接的交互方式就是调用这些生命周期的阶段。

clean 生命周期及其阶段

clean 生命周期包含以下阶段:

  • pre-clean:在清理之前完成一些所需的工作;
  • clean:删除之前构建出的所有文件;
  • post-clean:在清理之后完成一些所需的工作。

default 生命周期及其阶段

default 生命周期包含了实际构建时需要执行的所有步骤,是最重要的生命周期。该生命周期包含以下阶段:

  • validate:验证项目是否正确,所有必要信息是否可用;
  • initialize:初始化构建状态,例如设置 property 或创建目录;
  • generate-sources:生成要包含在编译中的任何源代码;
  • process-sources:处理源代码,例如替换所有引用的值;
  • generate-resources:生成要包含在包中的资源;
  • process-resources:将资源复制并处理到目标目录中,准备打包;
  • compile:编译项目的源代码;
  • process-classes:对编译生成的文件进行后期处理,例如对 Java 类进行字节码增强;
  • generate-test-sources:生成要包含在编译中的任何测试源代码;
  • process-test-sources:处理测试源代码,例如替换所有引用的值;
  • generate-test-resources:为测试创建资源;
  • process-test-resources:将资源复制并处理到测试目标目录中;
  • test-compile:将测试源代码编译到测试目标目录中;
  • process-test-classes:对测试编译生成的文件进行后期处理,例如对 Java 类进行字节码增强;
  • test:使用合适的单元测试框架运行测试。这些测试不应要求打包或部署代码;
  • prepare-package:在实际打包之前,执行准备打包所需的任何操作。这通常会生成已处理但尚未打包的所有文件和目录;
  • package:获取编译后的代码,并将其打包为可分发的格式,如 JAR;
  • pre-integration-test:在执行集成测试之前执行所需的操作。这可能涉及一些事项,如设置所需环境等;
  • integration-test:如有必要,处理包并将其部署到可以运行集成测试的环境中;
  • post-integration-test:执行集成测试后执行所需的操作。这可能包括清理环境;
  • verify:运行任何检查以验证包是否有效并符合质量标准;
  • install:将包安装到本地仓库中,作为本地其他项目中的依赖项使用;
  • deploy:在集成或发布环境中完成,将最终包复制到远程仓库,以便与其他开发人员和项目共享。

site 生命周期及其阶段

  • pre-site:在生成实际的项目站点之前执行所需的流程;
  • site:生成项目的站点文档;
  • post-site:执行完成站点生成所需的流程;
  • site-deploy:将生成的站点文档部署到指定的 web 服务器。

常见的命令行调用

每个生命周期内的阶段都是有顺序的,且后面的阶段依赖于前面的阶段。当调用某个生命周期的某个阶段时,则会尝试先依次调用该生命周期内位于该阶段前面的各个阶段。比如,当调用 clean 生命周期的 pre-clean 阶段时,仅有 pre-clean 阶段得以执行;当调用 clean 生命周期的 clean 阶段时,则会依次执行 pre-cleanclean 阶段;当调用 clean 生命周期的 post-clean 阶段时,则会依次执行 pre-cleancleanpost-clean 阶段。

这三个生命周期彼此都是独立的,用户可以仅调用 clean 生命周期的某个阶段,或者仅仅调用 default 生命周期的某个阶段,而不会对其他生命周期产生影响。

如果想要 jar 包,请运行 mvn package。如果要运行单元测试,请运行 mvn test

如果你不确定你想要什么,那就调用 mvn verify 命令。在 verify 阶段执行验证之前,将按顺序执行 default 生命周期中在 verify 阶段之前的其他每个阶段(validatecompilepackage 等),即只需要调用要执行的最后一个构建阶段即可。在大多数情况下,调用 verify 的效果与 package 相同。但是,如果存在集成测试,也将执行这些阶段。在 verify 阶段,可以进行一些额外的检查。例如,如果您的代码是根据预定义的 checkstyle 规则编写的。

在构建环境中,使用 mvn clean deploy 以下调用来干净地构建工件并将其部署到共享仓库中。同一命令可用于多模块场景(即具有一个或多个子项目的项目),Maven 将遍历每个子项目并执行 clean,然后执行 deploy(包括所有先前的构建阶段步骤)。

Maven 插件

概述

Maven 的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,实际的任务都是依靠插件来完成。每个构建步骤都可以绑定一个或多个插件行为,Maven 为大多数构建步骤编写并绑定了默认插件。当用户有特殊需要的时候,可以自己配置插件来定制构建行为,甚至可以使用自己编写的 Maven 插件

插件目标及其与阶段的绑定

插件往往能够完成多个任务。比如,maven-dependency-plugin 插件能够基于项目依赖做很多事情,它能够分析项目依赖来帮助找出潜在的无用依赖,它能够列出项目的依赖树来帮助分析依赖来源,它能够列出项目所有已解析的依赖等等。插件里的每项功能就是一个插件目标(plugin goal。上述提到的几个功能分别对应的插件目标为dependency:analyzedependency:treedependency:list。这是一种通用的写法,冒号前面是插件前缀,冒号后面是该插件的目标。类似地,还可以写出 compiler:compile (这是 maven-compiler-plugincompile 目标)和 surefire:test(这是 maven-surefire-plugintest 目标)。

Maven 生命周期中的阶段与插件目标相互绑定,用以完成实际的构建任务。插件目标可能绑定到零个或多个构建阶段。未绑定到任何阶段的插件目标可以通过直接调用从而在生命周期之外执行。执行顺序取决于调用插件目标和阶段的顺序。例如,下面的命令中的 cleanpackage 参数是构建阶段,而dependency:copy-dependencies 是插件的目标。

mvn clean dependency:copy-dependencies package

如果要执行上面的操作,将首先执行 clean 阶段(这意味着它将运行 clean 生命周期中位于 clean 阶段之前的所有阶段,加上 clean 阶段本身),然后执行 dependency:copy-dependencies 插件目标,最后执行 package 阶段(以及 default 生命周期中位于 package 阶段之前的所有阶段)。

如果一个插件目标绑定到一个或多个阶段,那么将在所有这些阶段中调用该插件目标。此外,某个阶段也可以有零个或多个插件目标。如果某个阶段没有绑定插件目标,则该阶段将不会执行,但如果该构建阶段有一个或多个插件目标,则该构建阶段将执行所有这些插件目标

注意:在 Maven 2.0.5 及更高版本中,绑定到一个阶段的多个插件目标的执行顺序与 POM 中插件目标的声明顺序相同,但是不支持同一插件的多个实例。在 Maven 2.0.11 及更高版本中,同一插件的多个实例按分组来一起执行和排序

不从命令行调用的阶段

用连字符(pre-*post-*、或 process-*)命名的阶段通常不会从命令行直接调用。这些阶段对构建进行排序,在构建之外生成没有用处的中间结果。比如,在调用 integration-test 时,环境可能处于挂起状态

代码覆盖工具(如 Jacoco)和容器插件(如 Tomcat、Cargo 和 Docker)将目标绑定到 pre-integration-test 阶段,以准备集成测试的容器环境。这些插件还将目标绑定到 post-integration-test 阶段,以收集覆盖率统计信息或停用集成测试容器。

故障保护和代码覆盖插件将目标绑定到 integration-testverify 阶段。最终结果是测试和覆盖率报告在 verify 阶段之后可用。如果非要从命令行调用 integration-test,则不会生成任何报告。更糟糕的是,集成测试容器环境处于挂起状态(空跑),Tomcat WebServer 或 Docker 实例保持运行,Maven 甚至可能不会自行终止。

内置绑定

为了能让用户几乎不用任何配置就能构建 Maven 项目,Maven 为一些主要的生命周期阶段绑定了很多插件目标,当用户通过命令行调用这些内置绑定好的阶段时,对应的插件目标就会执行相应的任务。Maven 在 META-INF/plexus/components.xml 文件中定义了 3 个生命周期及其绑定。

clean 生命周期中各阶段绑定的插件目标

Maven 在 META-INF/plexus/components.xml 中关于 clean 生命周期中各阶段及其绑定的目标如下:

<phases>
  <phase>pre-clean</phase>
  <phase>clean</phase>
  <phase>post-clean</phase>
</phases>
<default-phases>
  <clean>
    org.apache.maven.plugins:maven-clean-plugin:2.5:clean
  </clean>
</default-phases>

default 生命周期中各阶段绑定的插件目标

Maven 在 META-INF/plexus/components.xml 中关于 default 生命周期及其绑定的目标如下:

<phases>
  <phase>validate</phase>
  <phase>initialize</phase>
  <phase>generate-sources</phase>
  <phase>process-sources</phase>
  <phase>generate-resources</phase>
  <phase>process-resources</phase>
  <phase>compile</phase>
  <phase>process-classes</phase>
  <phase>generate-test-sources</phase>
  <phase>process-test-sources</phase>
  <phase>generate-test-resources</phase>
  <phase>process-test-resources</phase>
  <phase>test-compile</phase>
  <phase>process-test-classes</phase>
  <phase>test</phase>
  <phase>prepare-package</phase>
  <phase>package</phase>
  <phase>pre-integration-test</phase>
  <phase>integration-test</phase>
  <phase>post-integration-test</phase>
  <phase>verify</phase>
  <phase>install</phase>
  <phase>deploy</phase>
</phases>

default 生命周期的定义没有绑定任何插件,插件绑定在 META-INF/plexus/default-bindings.xml 文件中单独定义,因为每个打包类型都不同。

pom 打包所绑定的插件目标

META-INF/plexus/default-bindings.xml 文件中关于 pom 打包类型的默认绑定如下:

<phases>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
jar 打包所绑定的插件目标

META-INF/plexus/default-bindings.xml 文件中关于 jar 打包类型的默认绑定如下:

<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-jar-plugin:2.4:jar
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
ejb 打包所绑定的插件目标

META-INF/plexus/default-bindings.xml 文件中关于 ejb 打包类型的默认绑定如下:

<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-ejb-plugin:2.3:ejb
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
maven-plugin 打包所绑定的插件目标
<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-classes>
    org.apache.maven.plugins:maven-plugin-plugin:3.2:descriptor
  </process-classes>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-jar-plugin:2.4:jar,
    org.apache.maven.plugins:maven-plugin-plugin:3.2:addPluginArtifactMetadata
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
war 打包所绑定的插件目标

META-INF/plexus/default-bindings.xml 文件中关于 war 打包类型的默认绑定如下:

<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-war-plugin:2.2:war
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
ear 打包所绑定的插件目标

META-INF/plexus/default-bindings.xml 文件中关于 ear 打包类型的默认绑定如下:

<phases>
  <generate-resources>
    org.apache.maven.plugins:maven-ear-plugin:2.8:generate-application-xml
  </generate-resources>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <package>
    org.apache.maven.plugins:maven-ear-plugin:2.8:ear
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>
rar 打包所绑定的插件插件目标

META-INF/plexus/default-bindings.xml 文件中关于 rar 打包类型的默认绑定如下:

<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-rar-plugin:2.2:rar
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>

site 生命周期中各阶段绑定的插件目标

Maven 在 META-INF/plexus/components.xml 中关于 site 生命周期中各阶段及其绑定的目标如下:

<phases>
  <phase>pre-site</phase>
  <phase>site</phase>
  <phase>post-site</phase>
  <phase>site-deploy</phase>
</phases>
<default-phases>
  <site>
    org.apache.maven.plugins:maven-site-plugin:3.3:site
  </site>
  <site-deploy>
    org.apache.maven.plugins:maven-site-plugin:3.3:deploy
  </site-deploy>
</default-phases>

配置插件

在Maven中,有两种插件,构建和报告:

  • 构建插件在构建期间执行,并在 <build/> 元素中配置。
  • 报告插件在站点生成期间执行,并在 <reporting/> 元素中配置。

所有插件都应该具有最少的必需信息groupIdartifactIdversion建议始终定义每个插件的版本,以保证构建的可复制性。一个好的做法是在 <build><pluginManagement/></build> 元素中指定每个构建插件的版本。对于报告插件,请在 <reporting><plugins/></reporting> 元素中指定每个插件版本。通常会在父级 POM 中定义一个 <pluginManagement/> 元素来统一管理各插件的版本

一般配置

Maven 插件(构建插件和报告插件)通过指定 <configuration> 元素进行配置,其中 <configuration> 元素的子元素映射到 Mojo 类中的字段或 setter。Mojo 是 Maven plain Old Java Object 的缩写,Mojo 映射到一个插件目标,插件由一个或多个 Mojo 组成。例如,一个 Mojo 使用指定的超时时间和选项列表对特定的 URL 执行查询。Mojo 的定义可能如下所示:

/**
 * @goal query
 */
public class MyQueryMojo extends AbstractMojo {
    @Parameter(property = "query.url", required = true)
    private String url;
 
    @Parameter(property = "timeout", required = false, defaultValue = "50")
    private int timeout;
 
    @Parameter(property = "options")
    private String[] options;
 
    public void execute() throws MojoExecutionException {
        ...
    }
}

要使用所需的 URL、超时时间和选项,则需要从 POM 配置该 Mojo:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-myquery-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <url>http://www.foobar.com/query</url>
          <timeout>10</timeout>
          <options>
            <option>one</option>
            <option>two</option>
            <option>three</option>
          </options>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

配置中的元素与 Mojo 中的字段名称相匹配。映射机制可以通过检查字段的类型并确定是否可能进行适当的映射来处理数组。映射是直接进行的。比如,url 元素映射到 url 字段,timeout 元素映射到 timeout 字段,options 元素映射到 options 字段。

对于打算直接从 CLI 执行的 Mojo,其参数通常提供通过系统属性(Java 的 -D 选项可用于提供系统属性)而不是通过 POM 中的 <configuration> 部分进行配置。这些参数的插件注解将列出对应系统属性的表达式。在上面的 Mojo 中,参数 url 与表达式 ${query.url} 相关联,这意味着它的值可以由系统属性 query.url 指定,如下所示:

mvn myquery:query -Dquery.url=http://maven.apache.org

系统属性的名称不一定与 mojo 参数的名称匹配。虽然这是一种相当常见的做法,但经常会有插件为系统属性使用了一些前缀,以避免名称与其他系统属性冲突。也可能有少数插件参数使用与参数名称完全无关的系统属性(例如出于历史原因),因此,请务必仔细阅读插件文档

help 目标

大多数 Maven 插件都有一个 help 目标,即打印插件及其参数和类型的描述。例如,要查看 javadoc 目标的帮助,请键入:

mvn javadoc:help -Ddetail -Dgoal=javadoc

配置参数

映射简单类型

映射简单类型(如布尔或整数)非常简单。<configuration> 元素可能如下所示:

...
<configuration>
  <myString>a string</myString>
  <myBoolean>true</myBoolean>
  <myInteger>10</myInteger>
  <myDouble>1.0</myDouble>
  <myFile>c:\temp</myFile>
  <myURL>http://maven.apache.org</myURL>
</configuration>
...
映射复杂对象

映射复杂类型也相当简单。让我们看一个简单的示例,其中我们尝试映射 Person 对象的配置。<configuration/> 元素可能如下所示:

...
<configuration>
  <person>
    <firstName>Jason</firstName>
    <lastName>van Zyl</lastName>
  </person>
</configuration>
...

映射复杂对象的规则如下所示:

  • 必须有一个私有字段对应于要映射的元素的名称。因此在我们的例子中,person 元素必须映射到 Mojo 中的 person 字段。

  • 实例化的对象必须与 Mojo 本身在同一个包中。因此,如果您的 Mojo 位于 com.mycompany.mojo.query 中,那么映射机制将在该包中查找名为 Person 的对象。该机制将元素名称的第一个字母大写,并使用该名称搜索要实例化的对象。

  • 如果希望将要实例化的对象放在另一个包中,或使用更复杂的名称,请使用以下实现属性指定该名称:

    ...
    <configuration>
      <person implementation="com.mycompany.mojo.query.SuperPerson">
        <firstName>Jason</firstName>
        <lastName>van Zyl</lastName>
      </person>
    </configuration>
    ...
    

配置映射机制可以轻松地处理大多数集合,因此让我们通过几个示例向您展示它是如何完成的:

映射 List 类型

映射列表的工作方式与映射到数组的工作方式大致相同,在数组中,元素列表将映射到列表。因此,如果你有一种如下的 Mojo:

public class MyAnimalMojo extends AbstractMojo {
    @Parameter(property = "animals")
    private List animals;
 
    public void execute()
        throws MojoExecutionException
    {
        ...
    }
}

如果有一个名为 animals 的字段,则插件的配置如下所示:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-myanimal-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <animals>
            <animal>cat</animal>
            <animal>dog</animal>
            <animal>aardvark</animal>
          </animals>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

其中列出的每种动物都是 animals 字段中的条目。与数组不同,集合没有特定的组件类型。为了推导出列表项的类型,使用以下策略:

  • 如果 XML 元素包含 implementation 提示属性,则使用该属性;
  • 如果 XML 元素包含 . 号,将尝试将其作为完全限定的类名;
  • 尝试将 XML 标记(首字母大写)作为与正在配置的 mojo/object 所在包中的类;
  • 如果 XML 元素没有内容,则假定其类型为 String。否则,配置将失败。
映射 Map 类型

同样,您可以按如下方式定义 Map:

...
    @Parameter(property = "myMap")
    private Map myMap;
...
...
  <configuration>
    <myMap>
      <key1>value1</key1>
      <key2>value2</key2>
    </myMap>
  </configuration>
...
映射 Properties 类型

Properties 的定义应如下所示:

...
    @Parameter(property = "myProperties")
    private Properties myProperties;
...
...
  <configuration>
    <myProperties>
      <property>
        <name>propertyName1</name>
        <value>propertyValue1</value>
      </property>
      <property>
        <name>propertyName2</name>
        <value>propertyValue2</value>
      </property>
    </myProperties>
  </configuration>
...

配置构建插件

以下仅用于在 <build> 元素中配置构建插件。

使用 <executions> 元素

您还可以使用 <executions> 元素配置 Mojo。这最常用于打算参与构建生命周期的某些阶段的 Mojo。以 MyQueryMoo 为例,您可能会看到如下内容:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-myquery-plugin</artifactId>
        <version>1.0</version>
        <executions>
          <execution>
            <id>execution1</id>
            <phase>test</phase>
            <configuration>
              <url>http://www.foo.com/query</url>
              <timeout>10</timeout>
              <options>
                <option>one</option>
                <option>two</option>
                <option>three</option>
              </options>
            </configuration>
            <goals>
              <goal>query</goal>
            </goals>
          </execution>
          <execution>
            <id>execution2</id>
            <configuration>
              <url>http://www.bar.com/query</url>
              <timeout>15</timeout>
              <options>
                <option>four</option>
                <option>five</option>
                <option>six</option>
              </options>
            </configuration>
            <goals>
              <goal>query</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

id 为 execution1 的第一个 <execution> 元素将此配置绑定到 test 阶段。

第二个 <execution> 元素没有 <phase> 子元素,将会如何执行呢?目标可以有一个默认的阶段绑定,通过 Mojo 类的 @phase 注释来指定。如果目标有一个默认的阶段绑定,那么它将在该阶段执行。但是如果目标没有绑定到任何生命周期阶段,那么它就不会在构建生命周期中执行

请注意,虽然某个 <execution> 元素的 id 必须在 POM 中单个插件的所有 <execution> 元素中都是唯一的,但它们不必在 POM 的继承层次结构中也是唯一的,将会合并来自不同 POM 的相同 id 的 <execution> 元素。这同样适用于由 profile 定义的 <execution> 元素

如果我们有一个绑定了不同阶段的多个 <execution> 元素,将会如何执行呢?让我们再次使用上面的示例 POM,但这次我们将把 id 为 execution2<execution> 元素绑定到一个阶段。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        ...
        <executions>
          <execution>
            <id>execution1</id>
            <phase>test</phase>
            ...
          </execution>
          <execution>
            <id>execution2</id>
            <phase>install</phase>
            <configuration>
              <url>http://www.bar.com/query</url>
              <timeout>15</timeout>
              <options>
                <option>four</option>
                <option>five</option>
                <option>six</option>
              </options>
            </configuration>
            <goals>
              <goal>query</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

如果有多个 <execution> 元素绑定到不同的阶段,那么 Mojo 将针对指定的每个阶段都执行一次。也就是说,当构建阶段为 test 阶段时,将应用<configuration> 中的设置来执行 execution1,当构建阶段已处于 install 阶段时,将应用 <configuration> 中的设置来执行 execution2

现在,让我们来看另一个 Mojo 示例,它显示了 default 生命周期阶段绑定。

/**
 * @goal query
 * @phase package
 */
public class MyBoundQueryMojo extends AbstractMojo {
    @Parameter(property = "query.url", required = true)
    private String url;
 
    @Parameter(property = "timeout", required = false, defaultValue = "50")
    private int timeout;
 
    @Parameter(property = "options")
    private String[] options;
 
    public void execute() throws MojoExecutionException {
        ...
    }
}

在上面的 Mojo 示例中,MyBoundQueryMojo 默认绑定到 package 阶段(请参见 Mojo 类的 @phase 注释)。但是如果我们想在 install 阶段而不是在 package 执行这个 Mojo,我们可以使用 <execution> 下的 <phase> 子元素来将 Mojo 重新绑定到一个新的生命周期阶段

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-myquery-plugin</artifactId>
        <version>1.0</version>
        <executions>
          <execution>
            <id>execution1</id>
            <phase>install</phase>
            <configuration>
              <url>http://www.bar.com/query</url>
              <timeout>15</timeout>
              <options>
                <option>four</option>
                <option>five</option>
                <option>six</option>
              </options>
            </configuration>
            <goals>
              <goal>query</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

现在,MyBoundQueryMo 默认阶段已经从 package 阶段被 install 阶段所覆盖。

注意:<executions> 元素内部的配置与 <executions> 外部的配置不同,<executions> 内部的配置不能从直接命令行调用中使用,它们仅在所绑定的阶段被调用时应用。因此,如果想将 <configuration> 部分全局应用于插件的所有调用,则需要将其移到 <executions> 之外。

从 Maven 3.3.1 开始,您可以在命令行上指定插件目标所调用的 <execution> 的 id。因此,如果要从命令行运行上述插件及其特定的 execution1 配置,可以执行:

mvn myqyeryplugin:queryMojo@execution1
使用 <dependencies> 元素

您可以配置构建插件的依赖项,通常使用较新的依赖项版本。例如,Maven Antrun 插件版本 1.2 使用 1.6.5 版本的 Ant ,如果您想在运行此插件时使用最新的Ant 版本,则需要添加 <dependencies> 元素,如下所示:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.2</version>
        ...
        <dependencies>
          <dependency>
            <groupId>org.apache.ant</groupId>
            <artifactId>ant</artifactId>
            <version>1.7.1</version>
          </dependency>
          <dependency>
            <groupId>org.apache.ant</groupId>
            <artifactId>ant-launcher</artifactId>
            <version>1.7.1</version>
          </dependency>
         </dependencies>
      </plugin>
    </plugins>
  </build>
  ...
</project>
在构建插件中使用 <inherited> 元素

默认情况下,插件配置应该传播到子 POM,因此要中断继承,可以将 <inherited> 元素值设置为 false

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.2</version>
        <inherited>false</inherited>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>

配置报告插件

以下仅用于在 <reporting> 元素中配置报告插件。

在 pom 中的 <reporting> 元素与 <build> 元素中配置报告插件的行为不同。

mvn site 仅使用 <reporting> 元素中指定的每个报告插件的 <configuration> 元素中定义的参数,即 site 始终忽略 <build> 中指定的每个插件的 <configuration> 元素中定义的参数。

mvn aplugin:areportgoal 首先使用 <reporting> 元素中指定的每个报告插件的 <configuration> 元素中定义的参数;如果未找到参数,它将查找在<build> 中指定的每个插件的 <configuration> 元素中定义的参数。

使用 <reportSets> 元素

可以使用 <reportSets> 元素配置报告插件。在运行 mvn site 时,最常用于有选择地生成报告。以下内容将仅生成项目团队报告。

<project>
  ...
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-project-info-reports-plugin</artifactId>
        <version>2.1.2</version>
        <reportSets>
          <reportSet>
            <reports>
              <report>project-team</report>
            </reports>
          </reportSet>
        </reportSets>
      </plugin>
    </plugins>
  </reporting>
  ...
</project>

要排除所有报告,则 <reports> 元素中不要设置任何值:

  <reportSets>
    <reportSet>
      <reports/>
    </reportSet>
  </reportSets>

参考每个插件文档(比如 plugin-info.html)来了解可用的报告目标。

在报告插件中使用 <inherited> 标记

默认情况下,插件配置应该传播到子 POM,因此要中断继承,可以将 <inherited> 元素值设置为 false

<project>
  ...
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-project-info-reports-plugin</artifactId>
        <version>2.1.2</version>
        <inherited>false</inherited>
      </plugin>
    </plugins>
  </reporting>
  ...
</project>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容

  • 一、什么是生命周期 Maven的生命周期包括项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生产等...
    JarvisTH阅读 333评论 0 0
  • 所有项目的构建都是有生命周期的,这个生命周期包括:项目清理、初始化、编译、测试、打包、集成测试、验证、部署、站点生...
    zlcook阅读 2,763评论 0 21
  • Maven的所有实际操作都是由插件完成的,如果没有插件,Maven什么都不会干。(即时你没有在POM中配置 元素,...
    Liam666阅读 256评论 0 1
  • Maven的生命周期是对所有构建过程的抽象和统一。包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署...
    洛杨凡阅读 314评论 0 0
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,041评论 0 4