《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
,它能够给予项目依赖做很多事情。
-
它能够分析
项目依赖
,帮助找到潜在的无用依赖。 -
它能够列出
项目的依赖树
,帮助分析依赖的来源。 - 它能够列出项目所有依赖解析的依赖等等。
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
获取插件信息
在线插件信息
-
Apache
:
https://maven.apache.org/plugins/index.html
-
Codehaus
:
https://www.mojohaus.org/plugins.html
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是什么呢?
-
https://repo1.maven.org/maven2/org/apache/maven/plugins/
-
https://www.mojohaus.org/plugins.html
—
不可用!!
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>