Maven中Build Lifecycle(构建生命周期)
官方地址:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
构建生命周期基础
Maven基于构建生命周期的核心概念,这意味着构建和分发特定工件artifact(项目)的过程是明确定义的
对于构建项目的人来说,这意味着只需要学习一小部分命令就可以构建任何Maven项目,POM将确保他们获得所需的结果
maven有三个内置的构建生命周期
default:默认生命周期处理项目部署
clean:清理生命周期处理项目清理
site:站点生命周期处理项目站点文档的创建
构建生命周期由多个阶段组成
每个构建生命周期都由不同的构建阶段列表定义,其中构建阶段表示生命周期中的一个阶段
完整的生命周期:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference
validate
- validate the project is correct and all necessary information is availablecompile
- compile the source code of the projecttest
- test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployedpackage
- take the compiled code and package it in its distributable format, such as a JAR.verify
- run any checks on results of integration tests to ensure quality criteria are metinstall
- install the package into the local repository, for use as a dependency in other projects locallydeploy
- done in the build environment, copies the final package to the remote repository for sharing with other developers and projects.
这些生命周期阶段(以及此处未显示的其他生命周期阶段)按顺序执行以完成默认生命周期。
鉴于上面的生命周期阶段,这意味着当使用默认生命周期时,Maven将
- 首先验证项目
- 然后尝试编译源
- 运行这些源
- 运行这些测试
- 打包二进制文件(例如jar)
- 针对该包运行集成测试
- 验证集成测试
- 将验证的包安装到本地存储库
- 然后将安装的包部署到远程存储库
常用的命令行调用
您应该选择与结果匹配的阶段。如果你想要你的jar,运行 package,如果您想运行单元测试,请运行 test
如果您不确定您想要什么,则首选的调用阶段是
mvn verify
此命令在执行verify之前,按顺序(validate、compile、package等)执行每个默认生命周期阶段。您只需要调用要执行的最后一个构建阶段,在本例中是verify
在大多数情况下,效果与包装相同。但是,如果有集成测试,也将执行这些测试。在验证阶段,可以进行一些额外的检查,例如,如果您的代码是根据预定义的checkstyle规则编写的
在构建环境中,使用以下调用干净地构建工件并将其部署到共享存储库中
mvn clean deploy
同一命令可用于多模块场景(即具有一个或多个子项目的项目),Maven遍历每个子项目并执行clean,然后执行deploy(包括所有先前的构建阶段步骤)
构建阶段由插件目标组成
但是,即使构建阶段负责构建生命周期中的特定步骤,它执行这些职责的方式也可能有所不同
这是通过声明绑定到那些构建阶段的插件目标来实现的
插件目标表示一个特定的任务(比构建阶段更精细),它有助于项目的构建和管理,它可能绑定到零个或多个构建阶段
未绑定到任何构建阶段的目标可以通过直接调用在构建生命周期之外执行
执行顺序取决于调用目标和构建阶段的顺序。例如,考虑下面的命令,clean和package参数是构建阶段,而dependency:copy-dependencies是(插件的)目标
mvn clean dependency:copy-dependencies package
如果要执行此操作,将首先执行clean阶段(这意味着它将运行clean生命周期的所有先前阶段,加上clean阶段本身)
然后执行dependency:copy-dependencies goal,然后最后执行包阶段(及其默认生命周期的所有先前构建阶段)
如果一个目标绑定到一个或多个构建阶段,那么将在所有这些阶段中调用该目标。
构建阶段也可以有零个或多个目标绑定到它,如果构建阶段没有与之绑定的目标,那么该构建阶段将不会执行,但如果它有一个或多个目标,它将执行所有这些目标
有些阶段通常不从命令行调用
用连字符(pre-*、post-*或process-*)命名的阶段通常不会从命令行直接调用
这些阶段对构建进行排序,生成在构建之外没有用处的中间结果,在调用集成测试的情况下,环境可能处于挂起状态
代码覆盖工具(如Jacoco)和执行容器插件(如Tomcat、Cargo和Docker)将目标绑定到预集成测试阶段,以准备集成测试容器环境
这些插件还将目标绑定到集成后测试阶段,以收集覆盖率统计信息或使集成测试容器退役,故障保护和代码覆盖插件将目标绑定到集成测试和验证阶段
最终结果是测试和覆盖率报告在验证阶段之后可用,如果要从命令行调用集成测试,则不会生成报告
更糟糕的是,集成测试容器环境处于挂起状态;tomcatwebserver或Docker实例保持运行,Maven甚至可能不会自行终止
设置项目来使用构建生命周期
构建生命周期非常简单,但当您为项目构建Maven构建时,如何将任务分配给每个构建阶段
打包
第一种也是最常见的方法是通过同名的POM元素<packaging>为项目设置打包。一些有效的包装值是jar、war、ear和pom。如果没有指定打包值,它将默认为jar
每个包装都包含一个要绑定到特定阶段的目标列表,例如,jar打包将以下目标绑定到默认生命周期的构建阶段
Phase | plugin:goal |
---|---|
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)仅将目标绑定到安装和部署阶段
请注意,对于某些可用的打包类型,您可能还需要在POM的<build>部分中包含一个特定的插件,并为该插件指定<extensions>true</extensions>
Plexus插件就是一个需要它的插件,它提供了一个Plexus应用程序和Plexus服务打包
插件 Plugins
向阶段添加目标的第二种方法是在项目中配置插件,插件是为Maven提供目标的工件
此外,插件可以具有一个或多个目标,其中每个目标表示该插件的能力,例如,编译器插件有两个目标:compile和testCompile
前者编译主代码的源代码,而后者编译测试代码的源代码
正如您将在后面的部分中看到的,插件可以包含指示将目标绑定到哪个生命周期阶段的信息
请注意,单独添加插件是不够的—您还必须指定要作为构建的一部分运行的目标,已配置的目标将添加到已从所选打包绑定到生命周期的目标中
如果一个特定阶段绑定了多个目标,那么使用的顺序是首先执行打包中的目标,然后执行POM中配置的目标
注意,您可以使用<executions>元素来获得对特定目标顺序的更多控制
例如,Modello插件默认绑定其目标modello:java to 生成源阶段(注:modello:java goal 生成Java源代码)
因此,要使用Modello插件并让它从模型生成源代码并将其合并到构建中,您可以在<build>的<plugins>部分向POM添加以下内容:
<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,只有在生成源阶段才有意义,但有些目标可以在多个阶段中使用,而且可能没有合理的违约
对于这些,您可以自己指定阶段。例如,假设你有一个目标display:time that 将当前时间回显到命令行,并希望它在流程测试资源阶段运行,以指示测试何时启动。其配置如下:
<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>
睁开眼,书在面前 闭上眼,书在心里