构建生命周期简介

目录

构建生命周期基础

Maven 基于构建生命周期的核心概念。这意味着明确定义了构建和分发特定工件(项目)的过程。

对于构建项目的人来说,这意味着只需要学习一小部分命令来构建任何 Maven 项目,POM将确保他们得到他们想要的结果。

有三个内置的构建生命周期:默认、干净和站点。生命default周期处理您的项目部署,clean生命周期处理项目清理,而site生命周期处理项目网站的创建。

构建生命周期由阶段组成

这些构建生命周期中的每一个都由不同的构建阶段列表定义,其中构建阶段代表生命周期中的一个阶段。

例如,默认生命周期包含以下阶段(有关生命周期阶段的完整列表,请参阅生命周期参考):

  • validate- 验证项目是否正确并且所有必要的信息都可用
  • compile- 编译项目的源代码
  • test- 使用合适的单元测试框架测试编译的源代码。这些测试不应该要求打包或部署代码
  • package- 获取已编译的代码并将其打包成可分发的格式,例如 JAR。
  • verify- 对集成测试的结果进行任何检查,以确保满足质量标准
  • install- 将包安装到本地存储库中,作为本地其他项目的依赖项
  • deploy- 在构建环境中完成,将最终包复制到远程存储库以与其他开发人员和项目共享。

这些生命周期阶段(以及此处未显示的其他生命周期阶段)按顺序执行以完成default生命周期。鉴于上述生命周期阶段,这意味着当使用默认生命周期时,Maven 将首先验证项目,然后将尝试编译源代码,针对测试运行它们,打包二进制文件(例如 jar),针对该项目运行集成测试包,验证集成测试,将经过验证的包安装到本地存储库,然后将安装的包部署到远程存储库。

[顶部]

通常的命令行调用

您应该选择与您的结果相匹配的阶段。如果你想要你的 jar,运行package. 如果要运行单元测试,请运行test.

如果你不确定你想要什么,首选的调用阶段是

mvn verify

此命令在执行之前按顺序(validatecompilepackage等)执行每个默认生命周期阶段verify。您只需要调用要执行的最后一个构建阶段,在这种情况下,verify. 在大多数情况下,效果与 相同package。但是,如果有集成测试,这些也将被执行。在此verify阶段,可以进行一些额外的检查,例如,如果您的代码是根据预定义的检查样式规则编写的。

在构建环境中,使用以下调用干净地构建工件并将其部署到共享存储库中。

mvn clean deploy

同一命令可用于多模块方案(即具有一个或多个子项目的项目)。Maven 遍历每个子项目并执行clean,然后执行deploy(包括之前的所有构建阶段步骤)。

[顶部]

构建阶段由插件目标组成

但是,即使构建阶段负责构建生命周期中的特定步骤,它执行这些职责的方式也可能会有所不同。这是通过声明绑定到这些构建阶段的插件目标来完成的。

插件目标代表了一个特定的任务(比构建阶段更精细),它有助于项目的构建和管理。它可能绑定到零个或多个构建阶段。未绑定到任何构建阶段的目标可以通过直接调用在构建生命周期之外执行。执行顺序取决于调用目标和构建阶段的顺序。例如,考虑下面的命令。和参数是构建阶段,而clean是(插件的)目标。packagedependency:copy-dependencies

mvn clean dependency:copy-dependencies package

如果要执行此操作,clean则将首先执行阶段(意味着它将运行干净生命周期的所有先前阶段,加上clean阶段本身),然后是dependency:copy-dependencies目标,然后最终执行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-test阶段verifyverify最终结果是测试和覆盖率报告在该阶段之后可用。如果integration-test要从命令行调用,则不会生成报告。更糟糕的是集成测试容器环境处于挂起状态;Tomcat 网络服务器或 Docker 实例保持运行,Maven 甚至可能不会自行终止。

[顶部]

设置项目以使用构建生命周期

构建生命周期使用起来非常简单,但是当您为项目构建 Maven 构建时,您如何为每个构建阶段分配任务?

包装

第一种也是最常见的方法是通过同名的 POM 元素为您的项目设置打包<packaging>。一些有效的包装值是jarwar和。如果未指定包装值,则默认为.earpomjar

每个包装都包含一个绑定到特定阶段的目标列表。例如,jar打包将绑定以下目标以构建默认生命周期的阶段。

阶段 插件:目标
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar
install install:install
deploy deploy:deploy

这是一套几乎标准的绑定;但是,某些包装以不同的方式处理它们。例如,纯元数据(打包值为pom)的项目仅将目标绑定到installdeploy阶段(有关某些打包类型的目标到构建阶段绑定的完整列表,请参阅生命周期参考)。

请注意,对于某些可用的打包类型,您可能还需要在<build>POM 的部分中包含特定插件并<extensions>true</extensions>为该插件指定。需要此功能的插件的一个示例是 Plexus 插件,它提供了一个plexus-applicationplexus-service包装。

[顶部]

插件

将目标添加到阶段的第二种方法是在项目中配置插件。插件是为 Maven 提供目标的工件。此外,插件可能具有一个或多个目标,其中每个目标代表该插件的一种能力。例如,编译器插件有两个目标:compiletestCompile. 前者编译你的主要代码的源代码,而后者编译你的测试代码的源代码。

正如您将在后面的部分中看到的,插件可以包含指示将目标绑定到哪个生命周期阶段的信息。请注意,单独添加插件是不够的信息 - 您还必须指定要作为构建的一部分运行的目标。

已配置的目标将添加到已从所选包装绑定到生命周期的目标中。如果多个目标绑定到特定阶段,则使用的顺序是首先执行打包中的目标,然后执行 POM 中配置的目标。请注意,您可以使用该<executions>元素来更好地控制特定目标的顺序。

例如,Modello 插件默认将其目标绑定modello:javagenerate-sources阶段(注意:modello:java目标生成 Java 源代码)。因此,要使用 Modello 插件并让它从模型生成源代码并将其合并到构建中,您可以在 POM 的<plugins>部分添加以下内容<build>

...
 <plugin>
   <groupId>org.codehaus.modello</groupId>
   <artifactId>modello-maven-plugin</artifactId>
   <version>1.8.1</version>
   <executions>
     <execution>
       <configuration>
         <models>
           <model>src/main/mdo/maven.mdo</model>
         </models>
         <version>4.0.0</version>
       </configuration>
       <goals>
         <goal>java</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
...

您可能想知道为什么该<executions>元素存在。这样您就可以在需要时使用不同的配置多次运行相同的目标。还可以为单独的执行分配一个 ID,以便在继承或应用配置文件期间,您可以控制目标配置是合并还是转换为附加执行。

当给出与特定阶段匹配的多个执行时,它们将按照 POM 中指定的顺序执行,继承的执行首先运行。

现在,在 的情况下modello:java,它只在generate-sources相位中才有意义。但是有些目标可以在多个阶段使用,并且可能没有合理的默认值。对于那些,您可以自己指定阶段。例如,假设您有一个display:time将当前时间回显到命令行的目标,并且您希望它在process-test-resources阶段运行以指示测试何时开始。这将被配置为:

...
 <plugin>
   <groupId>com.mycompany.example</groupId>
   <artifactId>display-maven-plugin</artifactId>
   <version>1.0</version>
   <executions>
     <execution>
       <phase>process-test-resources</phase>
       <goals>
         <goal>time</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
...

[顶部]

生命周期参考

下面列出了default,cleansite生命周期的所有构建阶段,它们按照指定的顺序执行。

清洁生命周期

阶段 描述
pre-clean 在实际项目清洁之前执行所需的流程
clean 删除之前构建生成的所有文件
post-clean 执行完成项目清洁所需的流程

默认生命周期

阶段 描述
validate 验证项目是否正确并且所有必要的信息都可用。
initialize 初始化构建状态,例如设置属性或创建目录。
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 在集成或发布环境中完成,将最终包复制到远程存储库以与其他开发人员和项目共享。

网站生命周期

阶段 描述
pre-site 在实际项目站点生成之前执行所需的流程
site 生成项目的站点文档
post-site 执行完成站点生成和准备站点部署所需的流程
site-deploy 将生成的站点文档部署到指定的 Web 服务器

[顶部]

内置生命周期绑定

默认情况下,某些阶段具有绑定到它们的目标。而对于默认生命周期,这些绑定取决于打包值。以下是一些目标到构建阶段的绑定。

清理生命周期绑定

阶段 插件:目标
clean clean:clean

默认生命周期绑定 - 打包ejb/ ejb3/ jar/ par/ rar/war

阶段 插件:目标
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package ejb:ejb ejb3:ejb3 jar:jar par:par rar:rar war:war
install install:install
deploy deploy:deploy

默认生命周期绑定 - 打包ear

阶段 插件:目标
generate-resources ear:generate-application-xml
process-resources resources:resources
package ear:ear
install install:install
deploy deploy:deploy

默认生命周期绑定 - 打包maven-plugin

阶段 插件:目标
generate-resources plugin:descriptor
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar plugin:addPluginArtifactMetadata
install install:install
deploy deploy:deploy

默认生命周期绑定 - 打包pom

阶段 插件:目标
package
install install:install
deploy deploy:deploy

站点生命周期绑定

阶段 插件:目标
site site:site
site-deploy site:deploy

参考

完整的 Maven 生命周期由模块components.xml中的文件定义maven-core,并带有相关文档以供参考。

默认生命周期绑定在单独的default-bindings.xml描述符中定义。

有关直接取自源代码的最新文档,请参阅默认生命周期参考的生命周期参考插件绑定。

[顶部]