注意
想法及时记录,实现可以待做。
Maven的构建生命周期
只要理解了Maven的构建生命周期,才能保证Maven最后的构建结果是我们想要的。
Maven有三个内建的构建生命周期:default、clean和site。
default
周期可以处理项目组的部署,clean
周期可以处理项目的清理,而site
周期可以处理项目组的站点文档的创建。
构建生命周期是由各个构建阶段组成
每个构建生命周期都定义了多个不同的阶段。
- Clean
- pre-clean:在实际项目清理之前执行所需的过程
- clean:清理上一版本生成的所有文件
- post-clean:执行完成项目清理所需的过程
- Default
- 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:将最终的包发布到远程的仓库,这样就可以分享给其他开发者或者部署项目使用
- Site
- pre-site:在实际项目站点生成之前执行所需的过程
- site:生成项目站点的文档
- post-site:执行完成站点生成并为站点部署做准备所需的过程
- site-deploy:将生成的站点文档部署到指定的Web服务器
使用命令行调用
你可以选择符合结果的阶段,如果想要jar包,那么运行package
,如果想要单元测试,那么运行test
。
如果不知道想要啥,也许可以运行mvn verify
这个命令在真正执行verify
之前,会按顺序执行默认的生命周期的阶段(validate
,compile
,package
,等等)。你只需要调用最后一个阶段就可以。
在大多数的场景,我们最终执行的阶段都是package
。
在构建环境的时候,使用下面的命令,可以清理构建工作环境,然后部署最后的打包到共享仓库中:
mvn clean deploy
构建阶段由插件目标组成
一个构建阶段也许会有多个插件目标。clean
和package
是构建阶段,然而dependency:copy-dependencies
却是插件的一个目标,如下所示:
mvn clean dependency:copy-dependencies package
上述命令如果执行,那么clean
将会被首先执行(这也就是说会执行所有的清理周期的所有操作),然后就是执行dependency:copy-dependencies
这个目标,最后才会执行package
(所有的顺序之前的阶段,还包括自己)。
通常不从命令行调用某些阶段
通常不从命令行直接调用以连字词命名的阶段(pre-*,post- *或process- *)。这些阶段对构建进行排序,产生中间结果,这些结果在构建外部无用。在进行集成测试的情况下,环境可能处于挂起状态。
Jacoco等代码覆盖工具以及Tomcat,Cargo和Docker等执行容器插件将目标绑定到集成前测试阶段,以准备集成测试容器环境。 这些插件还将目标绑定到集成测试后阶段,以收集覆盖率统计信息或停用集成测试容器。
故障安全和代码覆盖插件将目标绑定到集成测试和验证阶段。 最终结果是测试,并且在验证阶段之后将提供覆盖率报告。 如果要从命令行调用Integration-test,则不会生成任何报告。 更糟糕的是,集成测试容器环境处于挂起状态; Tomcat Web服务器或Docker实例保持运行状态,并且Maven甚至无法自行终止。
设置项目以使用构建生命周期
构建生命周期很容易使用,但是当你为项目构建Maven构建时,如何为每个构建阶段分配任务呢?
打包
第一种也是最常见的方法是通过同名的POM元素
每个包都包含要绑定到特定阶段的目标列表。例如,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)的项目仅将目标绑定到安装和部署阶段。
插件
向阶段添加目标的第二种方法是在项目中配置插件。 插件是为Maven提供目标的构件。 此外,插件可以具有一个或多个目标,其中每个目标代表该插件的能力。 例如,编译器插件有两个目标:compile和testCompile。 前者编译你的主代码的源代码,而后者编译你的测试代码的源代码。
正如你将在后面的部分中看到的那样,插件可以包含指示目标绑定到哪个生命周期阶段的信息。 请注意,仅添加插件是不够的信息-还必须指定要在构建过程中运行的目标。
已配置的目标将从所选包中添加到已经绑定到生命周期的目标中。 如果在一个特定阶段上绑定了多个目标,则使用的顺序是先执行包中的目标,然后执行POM中配置的目标。 请注意,你可以使用
例如,默认情况下,Modello插件将其目标modello:java
绑定到generate-sources
阶段(注意:modello:java
目标生成Java源代码)。 因此,要使用Modello插件并使其从模型生成源并将其合并到构建中,你可以在
...
<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>
...