Maven生命周期和插件

maven的生命周期就是对所有的构建过程就行抽象和统一。maven从大量项目和构建工具中总结了一套高度完善的、易扩展的生命周期。这个生命周期包含项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有的构建步骤。Maven的生命周期是抽象的,其实际行为都是由插件来完成。

注意,maven的发音为: [ˈmeɪvn]


Maven的生命周期

Maven有三个内置的生命周期:

  • clean,负责清理项目
  • default,负责构建项目
  • site,负责建立项目站点

每个生命周期都包含一些阶段(phase),用户与maven最直接的交互方式就是调用这些周期的阶段。

clean生命周期及其阶段
clean生命周期包含以下阶段:

  • pre-clean: 在清理之前完成一些所需的工作
  • clean: 删除之前构建出的所有文件
  • post-clean:在清理之后完成的一些所需的工作

default生命周期及其阶段

default生命周期包含了实际构建时所需需要执行的所有步骤,是最重要的生命周期,包含以下阶段:

  • validate:验证项目是否正确,所有必要信息是否可用
  • initialize: 初始化构建状态,例如设置property或创建目录
  • generate-sources:生成需要编译的源代码
  • process-sources:处理源代码,例如替换所有引用的值
  • generate-resources:生成要包含在包中的资源
  • process-resources:将资源复制到目标目录中,准备打包
  • compile:编译项目的源代码
  • process-classes:对编译生成的文件进行后期处理,例如对Java类进行字节码增强
  • generate-test-sources:生成需要编译的测试源代码
  • process-test-sources:处理测试源代码,例如替换所有引用的值
  • test-compile:编译测试代码
  • process-test-classes:对测试代码编译生成的文件进行后期处理,例如字节码增强
  • test:使用合适的单元测试框架进行测试
  • prepare-package:在实际打包之前,执行准备打包所需的任何操作,通常会生成已处理但尚未打包的所有文件和目录
  • package:将编译好的代码打包成可发布的格式
  • pre-integration-test:在执行集成测试用例之前执行所需的操作,如设置环境等
  • integration-test:如有必要则对打好的包进行处理并将其部署到可以运行运行集成测试的环境中
  • post-integration-test:执行集成测试后所需的操作,例如清理环境
  • verify:运行任何检查以验证包是否有效并符合质量标准
  • install:将包安装到本地仓库中,作为本地其他项目中的依赖使用
  • deploy:在集成或发布环境中完成,将最终包复制到远程仓库

site生命周期及其阶段

  • pre-site:在生成实际的项目站点之前所需的操作
  • site:生成项目的站点文档
  • post-site:执行完成站点生成之后的操作
  • site-deploy:将生成的站点文档部署到指定的web服务器

命令行调用

每个生命周期内的阶段都是有顺序的,且后面的阶段依赖于前面的阶段。当调用某个生命周期的某个阶段时,则会尝试先依次调用该生命周期内位于该阶段前面的各个阶段。比如,当调用 clean 生命周期的 pre-clean 阶段时,仅有 pre-clean 阶段得以执行;当调用 clean 生命周期的 clean 阶段时,则会依次执行 pre-clean 、clean 阶段;当调用 clean 生命周期的 post-clean 阶段时,则会依次执行 pre-clean 、clean 、post-clean 阶段。

这三个生命周期彼此都是独立的,用户可以仅调用 clean 生命周期的某个阶段,或者仅仅调用 default 生命周期的某个阶段,而不会对其他生命周期产生影响。

如果想要 jar 包,请运行 mvn package。如果要运行单元测试,请运行 mvn test。

如果你不确定你想要什么,那就调用 mvn verify 命令。在 verify 阶段执行验证之前,将按顺序执行 default 生命周期中在 verify 阶段之前的其他每个阶段(validate、compile、package 等),即只需要调用要执行的最后一个构建阶段即可。在大多数情况下,调用 verify 的效果与 package 相同。但是,如果存在集成测试,也将执行这些阶段。在 verify 阶段,可以进行一些额外的检查。例如,如果您的代码是根据预定义的 checkstyle 规则编写的。

在构建环境中,使用 mvn clean deploy 以下调用来干净地构建工件并将其部署到共享仓库中。同一命令可用于多模块场景(即具有一个或多个子项目的项目),Maven 将遍历每个子项目并执行 clean,然后执行 deploy(包括所有先前的构建阶段步骤)。

Maven插件

Maven 的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,实际的任务都是依靠插件来完成。每个构建步骤都可以绑定一个或多个插件行为,Maven 为大多数构建步骤编写并绑定了默认插件。当用户有特殊需要的时候,可以自己配置插件来定制构建行为,甚至可以使用自己编写的 Maven 插件。

插件目标及其阶段的绑定

插件往往能完成多个任务。例如,maven-dependency-plugin插件能够基于项目依赖做很多事情:分析项目依赖来帮助找出潜在的无用依赖;列出项目的依赖树来帮助分析依赖来源;列出项目所有已解析的依赖等等。插件的每项功能就是一个插件目标,比如上述的几个功能分别对应插件目标:dependency:analyze, dependency:treedependency:list。这是一种通用的写法,冒号前面是插件前缀,后面是插件目标。

Maven生命周期中的阶段与插件目标相互绑定,用以完成实际的构建任务。插件目标可能绑定到多个构建阶段,也可能不绑定构建阶段。未绑定到任何构建阶段的插件目标可以通过直接调用从而在生命周期之外执行。执行顺序取决于调用插件目标和阶段的顺序。

举例说明,下面命令中的cleanpackage参数是构建阶段,而dependency:copy-dependencies是插件的目标。

mvn clean dependency:copy-dependencies package

如果要执行上面的操作,将首先执行clean阶段,然后执行 dependency:copy-dependencies 插件目标,最后执行 package 阶段。

如果一个插件目标绑定到一个或多个阶段,那么将在所有这些阶段中调用该插件目标。此外,某个阶段也可以有零个或多个插件目标。如果某个阶段没有绑定插件目标,则该阶段将不会执行,但如果该构建阶段有一个或多个插件目标,则该构建阶段将执行所有这些插件目标。

注意:在 Maven 2.0.5 及更高版本中,绑定到一个阶段的多个插件目标的执行顺序与 POM 中插件目标的声明顺序相同,但是不支持同一插件的多个实例。在 Maven 2.0.11 及更高版本中,同一插件的多个实例按分组来一起执行和排序。

不从命令行调用的阶段

用连字符(pre-*post-*process-*)命令的阶段通常不会从命令行直接调用。这些阶段对构建进行排序,在构建之外生成没有用处的中间结果。

代码覆盖工具(如 Jacoco)和容器插件(如 TomcatCargoDocker)将目标绑定到pre-integration-test 阶段,以准备集成测试的容器环境。这些插件还将目标绑定到 post-integration-test 阶段,以收集覆盖率统计信息或停用集成测试容器。

内置绑定

为了能让用户几乎不用任何配置就能构建 Maven 项目,Maven为一些主要的生命周期阶段绑定了很多插件目标,当用户通过命令行调用这些内置绑定好的阶段时,对应的插件目标就会执行相应的任务。Maven 在 META-INF/plexus/components.xml 文件中定义了 3 个生命周期及其绑定。

clean生命周期各阶段绑定的插件目标

Maven关于 clean 生命周期中各阶段及其绑定的目标如下:

<phases>
  <phase>pre-clean</phase>
  <phase>clean</phase>
  <phase>post-clean</phase>
</phases>
<default-phases>
  <clean>
    org.apache.maven.plugins:maven-clean-plugin:clean
  </clean>
</default-phases>

default生命周期中各阶段绑定的插件目标

default生命周期的定义没有绑定任何插件,其插件绑定会根据不同类型的打包方式在default-bindings.html中单独定义。

pom打包所绑定的插件目标

pom打包类型的默认绑定如下:

<phases>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>

jar包所绑定的插件目标

jar打包类型的默认绑定绑定如下:

<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-jar-plugin:2.4:jar
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>

war包默认绑定插件目标

war包默认绑定类型如下:

<phases>
  <process-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:resources
  </process-resources>
  <compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
  </compile>
  <process-test-resources>
    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
  </process-test-resources>
  <test-compile>
    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
  </test-compile>
  <test>
    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
  </test>
  <package>
    org.apache.maven.plugins:maven-war-plugin:2.2:war
  </package>
  <install>
    org.apache.maven.plugins:maven-install-plugin:2.4:install
  </install>
  <deploy>
    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
  </deploy>
</phases>

还有其他如rar, ear, maven-plugin等打包方式的默认绑定插件目标见参考资料1,这里不详细展开。

site生命周期中各阶段绑定的插件目标

site 生命周期中各阶段及其绑定的目标如下:

<phases>
  <phase>pre-site</phase>
  <phase>site</phase>
  <phase>post-site</phase>
  <phase>site-deploy</phase>
</phases>
<default-phases>
  <site>
    org.apache.maven.plugins:maven-site-plugin:3.3:site
  </site>
  <site-deploy>
    org.apache.maven.plugins:maven-site-plugin:3.3:deploy
  </site-deploy>

自定义绑定

除了内置绑定意外,用户还能自己选择将某个插件目标绑定到生命周期的的某个阶段上。例如一个常用的插件Maven ArchType Plugin,用户通过这个插件可以生成一个Maven项目的骨架,也可以从一个现成的项目中生成模板。

通常的用法是使用mvn archetype:create-from-project指令生成模板,将该插件目标绑定到default生命周期的package阶段,如下所示:

</plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-archetype-plugin</artifactId>
    <version>3.2.0</version>
      <executions>
        <execution>
          <id>create-archetype</id>
          <phase>package</phase>
          <goals>
            <goal>create-from-project</goal>
          </goals>
        </execution>
     </executions>
    </plugin>
</plugins>

在pom的build元素下的plugins子元素中声明插件的使用,除了配置插件的坐标声明外,还有插件的执行配置,executeions下每个execution子元素可以用来配置执行一个插件目标。

配置插件

在Maven中有两种插件,构建和报告:

  • 构建插件在构建期间执行,并在<build/>元素中配置
  • 报告插件在站点生成期间执行,并在 <reporting/> 元素中配置。

所有插件都应该具有最少的必需信息:groupIdartifactIdversion。建议始终定义每个插件的版本,以保证构建的可复制性。一个好的做法是在<build><pluginManagement/></build> 元素中指定每个构建插件的版本。对于报告插件,请在 <reporting><plugins/></reporting> 元素中指定每个插件版本。通常会在父级 POM 中定义一个 <pluginManagement/> 元素来统一管理各插件的版本。

命令行配置插件

插件目标支持命令行配置,可以通过-D参数,来配置插件目标的参数。例如命令 mvn install -Dmaven.test.skip=true ,就会跳过执行测试。

在pom中配置全局插件
并不是所有的插件参数都适合从命令行配置,有些参数的值从项目发布都不会改变,对于这种情况,可以在pom文件中一次性配置。例如需要配置maven-compiler-plugin编译java1.8。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>
    <plugins>
<build>

这样是不管绑定到compile阶段的maven-compiler-plugin:compile任务,还是绑定到test-compiler阶段的maven-compiler-plugin:testCompiler任务,就都能够使用该配置,基于1.8版本进行编译。

参考资料

[1].https://maven.apache.org/ref/3.8.6/maven-core/default-bindings.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值