Maven的生命周期

Maven的知识点

Posted by qin4zhang on February 1, 2020

注意

想法及时记录,实现可以待做。

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之前,会按顺序执行默认的生命周期的阶段(validatecompilepackage,等等)。你只需要调用最后一个阶段就可以。 在大多数的场景,我们最终执行的阶段都是package

在构建环境的时候,使用下面的命令,可以清理构建工作环境,然后部署最后的打包到共享仓库中:

mvn clean deploy

构建阶段由插件目标组成

一个构建阶段也许会有多个插件目标。cleanpackage是构建阶段,然而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,war,ear和pom。如果未指定包装值,则默认为jar。

每个包都包含要绑定到特定阶段的目标列表。例如,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插件并使其从模型生成源并将其合并到构建中,你可以在部分中将以下内容添加到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的情况下,仅在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>
...