maven生命周期&插件

  • Post author:
  • Post category:其他


《maven实战》 学习笔记



何为生命周期

在maven出现之前,项目构建的生命周期就已经存在了,软件开发人员每天都在对项目:

清理-编译-测试-部署



maven的生命周期就是为了对所有的构建过程进行抽象和同意。

maven的生命周期包括了:项目的

清理-初始化-编译-测试-打包-集成测试-验证-部署-站点生成

等几乎所有的构建步骤。

maven的生命周期是抽象的,它几乎不参与任何实际的工作,在maven的设计中,

实际任务都是交由插件来完成的



生命周期详解

maven拥有三套相互独立的生命周期。它们分别是


  • clean

    : 清理项目

  • default

    : 构建项目

  • site

    : 建立项目站点



clean 生命周期

包含三个阶段


  • pre-clean

    :

  • clean

    : 清理上一次构建生成的文件

  • post-clean



default 生命周期


  • validate


  • initialize


  • generate-sources


  • process-source

    : 处理项目主资源文件。 一般来说,是对

    src/main/resources

    目录内容进行

    变量替换

    等工作后,

    复制

    到项目输出的

    主classpath

    目录中。


  • generate-resources


  • process-resources


  • compile

    : 编译项目的主源码,一般来说,是对

    src/main/java

    目录下的文件进行编译,并输出至

    主classpath

    目录中.


  • process-classes


  • generate-test-sources


  • process-test-sources

    :处理项目测试资源文件。 一般来说,是对

    src/test/resources

    目录内容进行

    变量替换

    等工作后,

    复制

    到项目输出的

    测试classpath

    目录中。


  • generate-test-resources


  • process-test-resources


  • test-compile

    : 编译项目的测试源码,一般来说,是对

    src/test/java

    目录下的文件进行编译,并输出至

    测试classpath

    目录中.


  • process-test-classes


  • test

    : 使用单元测试框架运行测试,测试代码不会被打包或部署。


  • pre-package


  • package

    : 接收编译好的代码,打包成可发布的格式。 如JAR


  • pre-integration-test


  • integration-test


  • post-integration-test


  • verify


  • install

    : 将包安装到maven

    本地仓库

    ,供本地其它maven项目使用。


  • deploy

    :将包复制到

    远程仓库



site生命周期


  • pre-site

    :

  • site

    : 生成项目站点文档

  • post-site

  • site-deploy

    : 将项目站点发布到服务器上。



命令行与生命周期


  • mvn clean

    : 调用clean生命周期的clean阶段, 实际执行阶段为clean生命周期的

    pre-clean + clean

  • mvn test

    : 调用 default生命周期的test阶段。 实际执行为为default生命周期的

    validate,initialize ,..... test

  • mvn clean install

    :

    • 调用clean生命周期的clean阶段
    • 调用 default生命周期的test阶段

  • mvn clean deploy site-deploy

    • 调用clean生命周期的clean阶段
    • 调用default生命周期的deploy阶段
    • 调用生命周期的最后一个阶段



插件目标(plugin goal)

maven的核心仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的构建形式存在。

对于插件本身,

为了能够复用代码,它往往能够完成多个任务。



例如

:

maven-dependency-plugin

,它能够给予项目依赖做很多事情。

  1. 它能够分析

    项目依赖

    ,帮助找到潜在的无用依赖。
  2. 它能够列出

    项目的依赖树

    ,帮助分析依赖的来源。
  3. 它能够列出项目所有依赖解析的依赖等等。


maven-dependency-plugin

有十多个目标,每个目标对应了一个功能,上述提到的功能,分别对应的插件目标:

dependency:analyze, dependency:tree, dependency:list,

.

冒号前面是插件前缀,冒号后面是插件的目标。

dependcy对应的插件完整名称是:

org.apache.maven.plugins:maven-dependecncy-plugin



插件绑定

maven的生命周期与插件相互绑定,用以完成实际的构建任务。


例如

: 项目编译这一任务,它对应了

default生命周期的compile阶段

,而

maven-compiler-plugin

这一插件的

compile

目标能够完成该任务。 因此将二者绑定,就能实现项目的编译目的。

在这里插入图片描述



内置绑定

为了能让用户不用任何配置就能构建maven项目,maven在核心的一些主要的生命周期绑定了很多插件的目标,当用户通过命令行调用生命周期阶段时,对应的插件目标就会执行相应的任务 。

在这里插入图片描述

在这里插入图片描述

执行

mvn clean install

查看执行了哪些插件目标:

[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ test-reports ---
[INFO] Deleting /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ test-reports ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ test-reports ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 11 source files to /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ test-reports ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ test-reports ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 3 source files to /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ test-reports ---
[INFO] Surefire report directory: /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Configuring TestNG with: org.apache.maven.surefire.testng.conf.TestNG652Configurator@7e2d773b
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.117 sec

Results :

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0


[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ test-reports ---
[INFO] Building jar: /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/target/test-reports-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ test-reports ---
[INFO] Installing /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/target/test-reports-1.0-SNAPSHOT.jar to /usr/local/repositories/mvn_repo/cn/jhs/test-reports/1.0-SNAPSHOT/test-reports-1.0-SNAPSHOT.jar
[INFO] Installing /Users/huaijian/workspaces/idea/_self_project/test-reports/test-reports/pom.xml to /usr/local/repositories/mvn_repo/cn/jhs/test-reports/1.0-SNAPSHOT/test-reports-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.551 s
[INFO] Finished at: 2023-04-12T17:22:49+08:00
[INFO] ------------------------------------------------------------------------



自定义绑定

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-source-plugin</artifactId>
   <version>3.0.0</version>
   <executions>
     <execution>
       <id>attach-source</id>
       <phase>verify</phase>
       <goals>
         <goal>jar-no-fork</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

执行** mvn verify**就能看到如下输出:

[INFO] --- maven-source-plugin:3.0.0:jar-no-fork (attach-source) @ test-reports ---



如何查看默认绑定phase

将上一节的

<phase>

行删除。

执行命令:

mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:3.0.0 -Ddetail

source:test-jar-no-fork
  Description: This goal bundles all the test sources into a jar archive.
    This goal functions the same as the test-jar goal but does not fork the
    build, and is suitable for attaching to the build lifecycle.
  Implementation: org.apache.maven.plugins.source.TestSourceJarNoForkMojo
  Language: java
  Bound to phase: package



插件配置

完成插件和生命周期的绑定后,用户还可以配置插件目标的参数,进一步调整插件目标执行的任务,以满足项目需求。



命令行插件配置

如:

maven-surefire-plugin

提供了一个

maven.test.skip

参数,当其值为true时,就可以

跳过执行测试。

$ mvn install -Dmaven.test.skip=true



pom中插件全局配置

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-compiler-plugin</artifactId>
   <version>3.0.0</version>
   <configuration>
     <source>1.8</source>
     <target>1.8</target>
   </configuration>
 </plugin>

不管是

compile阶段



maven-compiler-plugin:compile

任务,

还是

test-compile阶段



maven-compiler-plugin:testCompile

任务,

都使用该配置,基于jdk1.8进行编译。



pom中插件任务配置


maven-antrun-plugin

为例,它有一个目标

run

,可以在maven中调用Ant任务。

 <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.3</version>
        <executions>
          <execution>
            <id>ant-validate</id>
            <phase>validate</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <tasks>
                <echo>i'm bound to validate phase</echo>
              </tasks>
           </configuration>
          </execution>
          <execution>
            <id>ant-verify</id>
            <phase>verify</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <tasks>
                <echo>i'm bound to verify phase</echo>
              </tasks>
            </configuration>
          </execution>
        </executions>
      </plugin>

执行命令:

mvn verify


[INFO] --- maven-antrun-plugin:1.3:run (ant-validate) @ test-reports ---
[INFO] Executing tasks
     [echo] i'm bound to validate phase
[INFO] Executed tasks

.....
.....

[INFO] --- maven-antrun-plugin:1.3:run (ant-verify) @ test-reports ---
[INFO] Executing tasks
     [echo] i'm bound to verify phase
[INFO] Executed tasks



获取插件信息



在线插件信息



maven-help-plugin 描述插件


mvn help:describe -Dplugin=GROUPID:ARTIFACTID:VERSION



从命令行调用插件

% mvn -h 

usage: mvn [options] [<goal(s)>] [<phase(s)>]


options

: mvn有20多个可选项,暂不表述。 mvn命令后面可以添加

多个goal 和phase

在这里插入图片描述



maven 插件解析机制



插件仓库

在这里插入图片描述



插件默认groupId

为了简化配置和使用,如果插件是maven官方插件:即groupId:

org.apache.maven.plugins

,就可以

省略groupId配置。



解析插件版本

同样为了简化配置和使用,用户在没有指定插件版本的情况下,maven会

自动化解析插件版本。


首先,在maven

超级POM

为所有

核心插件

设定了版本。


超级POM

是所有maven项目的父POM.

如果用户使用插件时没有指定版本,且插件也不是核心插件,

maven会去检查所有仓库的可用版本然后做出选择。

仓库元数据: groupId/artifactId/maven-metadata.xml



maven-compiler-plugin

为例,它的元数据:

https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml

<metadata>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<versioning>
<latest>3.11.0</latest>
<release>3.11.0</release>
<versions>
<version>2.0-beta-1</version>
<version>2.0</version>
<version>2.0.1</version>
<version>2.0.2</version>
<version>2.1</version>
<version>2.2</version>
<version>2.3</version>
<version>2.3.1</version>
<version>2.3.2</version>
<version>2.4</version>
<version>2.5</version>
<version>2.5.1</version>
<version>3.0</version>
<version>3.1</version>
<version>3.2</version>
<version>3.3</version>
<version>3.5</version>
<version>3.5.1</version>
<version>3.6.0</version>
<version>3.6.1</version>
<version>3.6.2</version>
<version>3.7.0</version>
<version>3.8.0</version>
<version>3.8.1</version>
<version>3.9.0</version>
<version>3.10.0</version>
<version>3.10.1</version>
<version>3.11.0</version>
</versions>
<lastUpdated>20230227075825</lastUpdated>
</versioning>
</metadata>

Maven 遍历本地仓库和所有远程插件仓库,将该路径下的仓库元数据归并后,就能计算出

latest 和release

的值。


  • latest

    表示所有仓库中该构件的

    最新版本


  • release

    表示最新的

    非快照版本

在Maven 2中,插件的版本会被解析至latest。也就是说,当用户使用某个非 核心插件且没有声明版本的时候,Maven 会将版本解析为所有可用仓库中的最新版本,面 这个版本也

可能是快照版



解析插件前缀

前面讲到mvn 命令行支持使用

插件前缀

来简化插件的调用,

现在解释Maven 如何根据插件前缀解析得到插件的坐标。

插件前缀与

groupld:artifactld

是一一对应的,这种几配关系存储在仓库元数据中 。

与之 前提到的

groupld/artifactld/maven-metadata.xml


不同

,这里的仓库元数据为

groupld/maven-metadate.xml

,那么这里的groupld是什么呢?

Maven在解析捕件仓库元数据的时候,会默认使用

org apache.maven.plugins



org.codehaus.mojo

两个groupld。也可以通过配置

settings.xml

让 Maven 检查其他 groupld 上的插件仓库元数据:

在这里插入图片描述

基于该配置,Maven 就不仅仅会检查

org/apache/maven/plugins/maven-metadata.xml



org/codehaus/mojo/maven-metadata.xml

还会检查

com/your/plugins/maven-metadata.xml



插件仓库元数据内容



https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml

为例:

<metadata>
<plugins>
<plugin>
<name>Apache Maven ACR Plugin</name>
<prefix>acr</prefix>
<artifactId>maven-acr-plugin</artifactId>
</plugin>
<plugin>
<name>Apache Maven Ant Plugin</name>
<prefix>ant</prefix>
<artifactId>maven-ant-plugin</artifactId>
</plugin>
....
</plugins>
</metadata>