携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
前言
本文为译文,笔者没有系统的学过maven开始还以为clean和install是一个生命周期,最近在使用插件jacoco指定了phase和goal有点疑惑,所以就看了下官方文档对生命周期的介绍。
构建生命周期基础
Maven的核心概念是构建生命周期。这意味着构建和分发特定工件(项目)是明确定义的。
对于构建项目的人,这意味着只需要学习一小部分命令就可以构建任何maven项目,POM确保他们得到他们想要的结果。
有三种内置的构建生命周期:default,clean和site。default生命周期处理项目部署,clean生命周期处理项目清理,site生命周期处理项目文档网站的创建。
构建生命周期由阶段组成
每个构建生命周期都由不同的构建阶段列表定义,其中构建阶段表示生命周期中的一个阶段。
例如,default的生命周期包含以下阶段(要获得生命周期阶段的完整列表,请参阅生命周期):
- validate - 验证项目是正确的,所有必要的信息都是可用的
- compile - 编译项目的源码
- test - 使用合适的单元测试框架测试编译后的源码。这些测试不应该要求代码打包或部署
- package - 获取编译后的源码,并将其打包成可分发的格式,例如JAR。
- verify - 运行对集成测试结果的任何检查,以确保满足质量标准
- install - 将包安装到本地仓库中,以便在本地的其他项目中作为依赖使用
- deploy - 在构建环境中完成,将最终的包复制到远程仓库,以便与其他的开发人员和项目共享。
这些生命周期阶段(以及这里没有显示的其他生命周期阶段)是按照顺序执行的,以完成default的生命周期。考虑到上面的生命周期,这意味着当使用default生命周期时,Maven将第一步验证项目,然后将编译源,跑单测,打包二进制文件(例如jar),使用包进行集成测试,验证继承测试,将装验证好的包安装到本地仓库,然后将安装到本地仓库的包打到原创仓库中。
常用的命令行调用
您应该选择与您的结果相匹配的阶段。如果你想要jar包,运行package。如归你想运行单测,运行test。
如果你不确定你想要的,首选的的调用阶段是:
mvn verify
该命令按序执行默认的生命周期(validate,compile,package,等),在执行verify之前。你仅需要调用要执行的最后一个构建阶段,例如在这个例子中的verify。在大多数情况下效果和package相同。然而,如果有集成测试,将被执行。在验证阶段,可以不做一些额外的检查,例如你的代码是根据预定义检查风格规则编写的。
在构建环境中,使用以下命令将构建干净并部署到共享存储库中:
mvn clean deploy
相同的命令可以在多模块场景中使用。
构建阶段是由插件目标构成的
然而,即使构建阶段负责构建生命周期的特定步骤,它履行这些职责的方式可能有所不同,并且这是由声明插件目标绑定到这些构建阶段来完成的。
插件目标代表一个特定的任务(比构建阶段更细),它有责于项目的构建和管理。它可以绑定零个或多个构建阶段。不绑定到任何构建阶段的目标可以通过直接调用在构建生命周期之外执行。执行的顺序取决于调用目标和构建阶段的顺序。例如考虑一下命令。clean和package参数是构建阶段,而dependency:copy-dependencies是目标(插件的):
mvn clean dependency:copy-dependencies package
如果要执行此操作,那么首先执行的阶段是clean(这意味着它将运行clean生命周期的所有前阶段,加上clean阶段本身),然后执行dependency:copy-dependencies目标,在最后执行package阶段(以及默认的生命周期之前的构建阶段)之前。
此外,如果一个目标绑定到一个或者多个构建阶段,目标将被在所有那些阶段调用。
而且,一个阶段可以绑定一个或者多个目标。如果一个构建阶段没有绑定目标,那么这个构建阶段将不会执行。但是如果有一个或者多个目标绑定到该阶段,将执行全部目标。
注意: 在Maven 2.0.5及以上,多个绑定到一个阶段的目标是被按照在POM文件中声明的顺序执行,但不支持同一个插件的多个实例。在Maven2.0.11及以上同一个插件的多个实例被组合在一起执行并排序。
设置项目以使用构建生命周期
构建生命周期使用起来足够简单,但是当你使用Maven构建项目时,你如何着手将任务分配给每个构建阶段呢?
packaging
第一种,也是最常见的方法,通过POM文件的<packaging>
元素指定你的项目打包方式。一些有效的packaging是jar、war、ear和pom。如果不指定jar是默认的。
每个packaging都包含要绑定到特定阶段的目标列表。例如,jar packaging将绑定以下目标来构建默认生命周期的各个阶段。
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 |
这几乎是一组标准的绑定;但是有些packagins以不同的方式处理它们。例如,一个项目是存粹的元数据(packaging是pom)仅绑定目标到install和deploy阶段(有关某些打包类型的目标到构建阶段绑定的完整列表,请参阅生命周期参考)。
注意,对于某些可用的packaging类型,你也许需要在POM文件的<build>
中包含一个特定的插件,并为插件指定<extensions>true</extensions>
。Plexus插件就是一个需要这样做的插件,它提供了Plexus-application和Plexus-service打包。
插件
第二种在你的项目中绑定目标到阶段的方式是配置插件。插件是为Maven提供目标的工件。此外,一个插件可能有一个或者多个目标,其中每个目标代表该插件的一种能力。例如,Compiler插件有两个目标:compile和testCompile。前者编译主代码的源码,而后者编译测试代码的源码。
正如您将在后面的部分中看到的,插件可以包含指示将目标绑定到哪个生命周期阶段的信息。注意添加插件本身它是不够的-你必须指定你想运行的goals作为你的构建部分。
配置的目标将添加到已绑定到所选打包的生命周期的目标中。如果将多个目标绑定到特定阶段,则使用的顺序是首先执行来自打包的目标,然后执行在POM文件中配置的golas。注意你可以使用<executions>
元素去获得对目标顺序的更多控制。
例如,Modello插件默认绑定它的目标modello:java至generate-sources阶段(注意:modello目标生成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,这样可以在继承或profiles应用过程中,你可以控制goal配置是合并还是转换为额外的执行。
当给出匹配特定阶段的多个执行时,它们将按照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、clean和site生命周期的所有构建阶段,这些阶段按照指定顺序执行。
Clean Lifecycle
Phase | Description |
---|---|
pre-clean | 执行实际项目清理之前所需的过程 |
clean | 清理之前构建生成的所有文件 |
post-clean | 执行完成项目清理所需的过程 |
Default Lifecycle
Phase | Description |
---|---|
validate | 验证项目是否正确并且所有所需信息是否可用 |
initialize | 初始化构建阶段,例如设置属性和创建目录 |
generate-sources | 生成用于编译的任何源码 |
process-sources | 处理源码,例如过滤一些值 |
generate-resources | 生成包含在包中的资源 |
process-resources | 将资源复制并处理到目标目录中,准备打包 |
compile | 编译项目中的源码 |
process-classes | post-process编译生成的文件,例如对Java classes做字节增强。 |
generate-test-sources | 生成编译中包含的任何测试源码 |
process-test-sources | 处理测试源码,例如过滤一些值 |
generate-test-resources | 生成测试资源 |
process-test-resources | 将资源复制并处理到测试目标目录中。 |
test-compile | 将测试源代码编译到测试目标目录中 |
process-test-classes | post-process测试编译生成的文件,例如对Java classes做字节增强。 |
test | 使用它一个合适的单测框架运行测试。这些测试不应该要求代码被打包或者被部署 |
prepare-package | 在真正打包之前,执行一些必要的预打包操作。这通常会导致包的解包、处理版本 |
package | 对编译的源码打包成可分发的格式,比如JAR |
pre-integration-test | 在集成测试被执行执行执行所需的动作。例如设置所需的环境 |
integration-test | 如果有必要,在可以运行集成测试的环境中处理和部署包。 |
post-integration-test | 在继承测试结束后执行所需的动作。例如清理环境 |
verify | 运行任何检查以验证包装有效并符合质量标准。 |
install | 将包安装到本地仓库中,以便在本地的其他项目中作为依赖使用 |
deploy | 在构建环境中完成,将最终的包复制到远程仓库,以便与其他的开发人员和项目共享 |
Site Lifecycle
Phase | Description |
---|---|
pre-site | 在实际项目site生成之前,执行所需的流程 |
site | 生成项目site文档 |
post-site | 执行完成site生成所需的步骤,并为site部署做准备 |
site-deploy | 部署生成的site文档到指定的web服务器。 |
内置生命周期绑定
一些生命周期默认绑定了goals。对于默认生命周期,这些绑定依赖于打包值。下面是一些构建阶段绑定的goal。
Clean Lifecycle Bindings
Phase | plugin:goal |
---|---|
clean | clean:clean |
Default Lifecycle Bindings - Packaging ejb
/ ejb3
/ jar
/ par
/ rar
/ war
Phase | plugin:goal |
---|---|
process-resources | resources:resources |
compile | compiler:compile |
process-test-resources | resources:testResources |
test-compile | compiler:testCompile |
test | surefire:test |
package | ejb:ejb or ejb3:ejb3 or jar:jar or par:par or rar:rar or war:war |
install | install:install |
deploy | deploy:deploy |
Default Lifecycle Bindings - Packaging ear
Phase | plugin:goal |
---|---|
generate-resources | ear:generate-application-xml |
process-resources | resources:resources |
package | ear:ear |
install | install:install |
deploy | deploy:deploy |
Default Lifecycle Bindings - Packaging maven-plugin
Phase | plugin:goal |
---|---|
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 and plugin:addPluginArtifactMetadata |
install | install:install |
deploy | deploy:deploy |
Default Lifecycle Bindings - Packaging pom
Phase | plugin:goal |
---|---|
package | |
install | install:install |
deploy | deploy:deploy |
Site Lifecycle Bindings
Phase | plugin:goal |
---|---|
site | site:site |
site-deploy | site:deploy |
参考
完整的Maven生命周期由Maven-core模块中的components.xml文件定义,并提供相关文档供参考。
默认的生命周期绑定是被单独定义在default-bindings.xml
描述。
查看Lifecycles Reference 和 Plugin Bindings for default Lifecycle Reference的最新文档,从源码中直接获取。