Maven 设计了插件机制,每个构建步骤都可以绑定一个或者多个插件行为,而且 Maven 为大多数构建步骤编写
并绑定了默认插件。例如,针对编译的插件有 maven-compiler-plugin,针对测试的插件有 maven-surefire-
plugin等。虽然在大多数时间里,用户几乎都不会觉察到插件的存在,但实际上编译是由 maven-compiler-plugin
完成的,而测试是由 maven-surefire-plugin 完成的。 当用户有特殊需要的时候,也可以配置插件定制构建行
为,甚至自己编写插件。
Maven 定义的生命周期和插件机制一方面保证了所有 Maven 项目有一致的构建标准,另一方面又通过默认插件
简化和稳定了实际项目的构建。此外,该机制还提供了足够的扩展空间,用户可以通过配置现有插件或者自行编写
插件来自定义构建行为。
Maven 拥有三套相互独立的生命周期,它们分别为 clean、default 和 site。clean 生命周期的目的是清理项
目,default 生命周期的目的是构建项目,而 site 生命周期的目的是建立项目站点。
每个生命周期包含一些阶段(phase),这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段,用户和 Maven
最直接的交互方式就是调用这些生命周期阶段。以 clean 生命周期为例,它包含的阶段有 pre-clean、clean 和
post-clean。 当用户调用 pre-clean 的时候,只有 pre-clean 阶段得以执行;当用户调用clean的时候,pre-clean
和 clean 阶段会得以顺序执行;当用户调用 post-clean 的时候,pre-clean、clean和 post-clean 会得以顺序执
行。
较之于生命周期阶段的前后依赖关系,三套生命周期本身是相互独立的,用户可以仅仅调用clean生命周期的某个
阶段,或者仅仅调用default生命周期的某个阶段,而不会对其他生命周期产生任何影响。例如,当用户调用
clean生命周期的 clean 阶段的时候,不会触发default生命周期的任何阶段,反之亦然,当用户调用default生命
周期的 compile 阶段的时候,也不会触发clean生命周期的任何阶段。
clean 声明周期的目的是清理项目,它包含是三个阶段:
pre-clean:执行一些清理前需要完成的工作。
clean:清理上一次构建生成的文件。
post-clean:执行一些清理后需要完成的工作
default声明周期定义了真正构建时所需要执行的所有步骤,它是生命周期中最核心的部分,其包含的阶段如下:
validate
initialize
generate-sources
process-sources:处理项目主资源文件。一般来说,是对src/main/resources目录的内容进行变量替换等工
作后,复制到项目输出的主classpath目录中。
generate-resources
process-resources
compile:编译项目的主源码。一般来说,是编译src/main/java目录下的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目录下的Java文件至项目输出的测试
classpath目录中。
process-test-classes
test:使用单元测试框架运行测试,测试代码不会打包或部署。
prepare-package
package:接受编译好的代码,打包成可发布的格式,如JAR。
pre-integration-test
integration-test
post-integration-test
verify
install:将包安装到Maven本地仓库,供本地其他Maven项目使用。
deploy:将最终的包复制到远程仓库,供其他开发人员和Maven项目使用。
官方文档:
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
site生命周期的目的是建立和发布项目站点,Maven 能够基于POM所包含的信息,自动生成一个友好的站点,方
便团队交流和发布项目信息。该声明周期包含如下阶段:
pre-site:执行一些在生成项目站点之前需要完成的工作。
site:生成项目站点文档。
post-site:执行一些在生成项目站点之后需要完成的工作。
site-deploy:将生成的项目站点发布到服务器上。
从命令行执行 Maven 任务的最主要方式就是调用 Maven 的生命周期阶段。需要注意的是,各个生命周期是相互
独立的,而一个生命周期的阶段是有前后依赖关系的。下面以一些常见的 Maven命令为例,解释其执行的生命周
期阶段:
$mvn clean
:该命令调用clean生命周期的 clean 阶段。实际执行的阶段为 clean生命周期的 pre-clean 和
clean 阶段。
$mvn test
:该命令调用 default生命周期的 test 阶段。实际执行的阶段为 default 生命周期的 validate、
initialize 等,直到test的所有阶段。这也解释了为什么在执行测试的时候,项目的代码能够自动得以编译。
$mvn clean install
:该命令调用 clean生命周期的clean 阶段和 default生命周期的install 阶段。实际执
行的阶段为 clean 生命周期的 pre-clean、clean 阶段,以及 default 生命周期的从 validate至 install 的所有
阶段。该命令结合了两个生命周期,在执行真正的项目构建之前清理项目是一个很好的实践。
$mvn clean deploy site-deploy
:该命令调用clean生命周期的clean阶段、default生命周期的 deploy 阶
段,以及 site 生命周期的 site-deploy 阶段。实际执行的阶段为clean生命周期的 pre-clean、clean 阶段,
default 生命周期的所有阶段,以及 site 生命周期的所有阶段。该命令结合了 Maven 所有三个生命周期,且
deploy 为default生命周期的最后一个阶段,site-deploy 为 site生命周期的最后一个阶段。
由于Maven 中主要的生命周期阶段并不多,而常用的 Maven 命令实际都是基于这些阶段简单组合而成的,因此
只要对 Maven 生命周期有一个基本的理解,读者就可以正确而熟练地使用 Maven 命令。
在进一步详述插件和生命周期的绑定关系之前,必须先了解插件目标(Plugin Goal)的概念。我们知道,Maven 的
核心仅仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的构件形式存在,因此,Maven 核
心的分发包只有不到3MB的大小,Maven 会在需要的时候下载并使用插件。
对于插件本身,为了能够复用代码,它往往能够完成多个任务。例如 maven-dependency-plugin,它能够基于项
目依赖做很多事情。它能够分析项目依赖,帮助找出潜在的无用依赖;它能够列出项目的依赖树,帮助分析依赖来
源;它能够列出项目所有已解析的依赖,等等。为每个这样的功能编写一个独立的插件显然是不可取的,因为这些
任务背后有很多可以复用的代码,因此,这些功能聚集在一个插件里,每个功能就是一个插件目标。
maven-dependency-plugin 有十多个目标,每个目标对应了一个功能,上述提到的几个功能分别对应的插件目标
为 dependency:analyze、dependency:tree 和 dependency:list。这是一种通用的写法,冒号前面是插件前缀,
冒号后面是该插件的目标。类似地,还可以写出 compiler:compile(这是 maven-compiler-plugin 的 compile 目
标)和 surefire:test(这是 maven-surefire-plugin 的 test 目标)。
Maven 的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标相互
绑定,以完成某个具体的构建任务。例如项目编译这一任务,它对应了 default生命周期的 compile 这一阶段,而
maven-compiler-plugin这一插件的 compile目标能够完成该任务。因此,将它们绑定,就能实现项目编译的目
的。
为了能让用户几乎不用任何配置就能构建 Maven 项目,Maven 在核心为一些主要的生命周期阶段绑定了很多插
件的目标,当用户通过命令行调用生命周期阶段的时候,对应的插件目标就会执行相应的任务。
clean生命周期仅有 pre-clean、clean 和 post-clean 三个阶段,其中的clean与maven-clean-plugin:clean 绑定。
maven-clean-plugin 仅有 clean这一个目标,其作用就是删除项目的输出目录。clean生命周期阶段与插件目标的
绑定关系如下表所示。
生命周期阶段 | 插件目标 |
---|---|
pre-clean | |
clean | maven-clean-plugin:clean |
post-clean |
site 生命周期有 pre-site、site,post-site 和 site-deploy 四个阶段,其中,site 和maven-site-plugin:site 相互绑
定,site-deploy 和 maven-site-plugin:depoy 相互绑定。maven-site-plugin 有很多目标,其中,site 目标用来生
成项目站点,deploy目标用来将项目站点部署到远程服务器上。site生命周期阶段与插件目标的绑定关系如下表所
示。
生命周期阶段 | 插件目标 |
---|---|
pre-site | |
site | maven-site-plugin:site |
post-site | |
site-deploy | maven-site-plugin:deploy |
相对于clean和site生命周期来说,default生命周期与插件目标的绑定系就显得复杂一些。这是因为对于任何项目
来说,例如jar项目和war项目,它们的项目清理和站点生成任务是一样的,不过构建过程会有区别。例如jar 项目
需要打成JAR 包,而war 项目需要打成WAR包。
由于项目的打包类型会影响构建的具体过程,因此,default生命周期的阶段与插件目标的绑定关系由项目打包类
型所决定,打包类型是通过POM中的 packaging元素定义的。最常见、最重要的打包类型是jar,它也是默认的打
包类型。基于该打包类型的项目,其 default 生命周期的内置插件绑定关系及具体任务如下表所示。
生命周期阶段 | 插件目标 | 执行任务 |
---|---|---|
process-resources | maven-resources-plugin:resources | 复制主资源文件至主输出目录 |
compile | maven-compile-plugin:compile | 编译主代码至主输出目录 |
process-test-resources | maven-resources-plugin:testRresources | 复制测试资源文件至测试输出目录 |
test-compile | maven-compiler-plugin:testCompile | 编译测试代码至测试输出目录 |
test | maven-surefire-plugin:test | 执行测试用例 |
package | maven-jar-plugin:jar | 创建项目jar包 |
install | maven-install-plugin:install | 将项目输出构件安装到本地仓库 |
deploy | maven-deploy-plugin:deploy | 将项目输出构件部署到远程仓库 |
注意,上表只列出了拥有插件绑定关系的阶段,default 生命周期还有很多其他阶段,默认它们没有绑定任何插
件,因此也没有任何实际行为。
除了默认的打包类型 jar 之外,常见的打包类型还有war、pom、maven-plugin、ear 等。
它们的 default 生命周期与插件目标的绑定关系可参阅 Maven 官方文档:
https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Built-in_Lifecycle_Bind-ings
读者可以从Maven的命令行输出中看到在项目构建过程执行了哪些插件目标,例如执行 mvn clean install 命令,
可以看到如下输出:
$ mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-maven ---
[INFO] Deleting D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ hello-maven ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\ta
rget\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\Hell
oMaven\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ hello-maven ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\ta
rget\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-maven ---
[INFO] Surefire report directory: D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\ta
rget\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.apache.HelloWorldTest
init
Tests run: 2, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.053 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-maven ---
[INFO] Building jar: D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-ma
ven-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-shade-plugin:3.2.4:shade (default) @ hello-maven ---
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-
1.0-SNAPSHOT.jar with D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-m
aven-1.0-SNAPSHOT-shaded.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ hello-maven ---
[INFO] Installing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven
-1.0-SNAPSHOT.jar to D:\DecompressionSoftwareInstall\apache-maven-3.3.9-bin\repository\org\example\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHO
T.jar
[INFO] Installing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\pom.xml to D:\Deco
mpressionSoftwareInstall\apache-maven-3.3.9-bin\repository\org\example\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.194 s
[INFO] Finished at: 2023-10-15T11:22:23+08:00
[INFO] Final Memory: 21M/310M
[INFO] ------------------------------------------------------------------------
从输出中可以看到,执行的插件目标依次为 maven-clean-plugin:clean、
maven-resources-plugin:resources、maven-compiler-plugin:compile、
maven-resources-plugin:testResources、maven-compiler-plugin:testCompile、
maven-surefire-plugin:test、maven-jar-plugin:jar 和 maven-install-plugin:install。
我们知道,mvn clean install 令实际调用了 clean 生命周期的 pre-clean、clean 阶段,以及default生命周期的从
validate至install 所有阶段。在此基础上,通过对照上面的几个表,就能从理论上得到将会执行的插件目标任务,
而实际的输出完全验证了这一点。
除了内置绑定以外,用户还能够自己选择将某个插件目标绑定到生命周期的某个阶段上,这种自定义绑定方式能让
Maven 项目在构建过程中执行更多更富特色的任务。
一个常见的例子是创建项目的源码jar包,内置的插件绑定关系中并没有涉及这一任务,因此需要用户自行配置。
maven-source-plugin 可以帮助我们完成该任务,它的jar-no-fork目标能够将项目的主代码打包成jar文件,可以
将其绑定到 default生命周期的 verify 阶段上,在执行完集成测试后和安装构件之前创建源码 jar包。具体配置见
代码:
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-source-pluginartifactId>
<version>3.2.1version>
<executions>
<execution>
<id>attach-sourcesid>
<phase>verifyphase>
<goals>
<goal>jar-no-forkgoal>
goals>
execution>
executions>
plugin>
运行 mvn verify 就能看到如下输出:
$ mvn verify
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ hello-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\Hell
oMaven\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ hello-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-maven ---
[INFO] Surefire report directory: D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\ta
rget\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.apache.HelloWorldTest
init
Tests run: 2, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.053 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-maven ---
[INFO] Building jar: D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-ma
ven-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-shade-plugin:3.2.4:shade (default) @ hello-maven ---
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-
1.0-SNAPSHOT.jar with D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-m
aven-1.0-SNAPSHOT-shaded.jar
[INFO]
[INFO] --- maven-source-plugin:3.2.1:jar-no-fork (attach-sources) @ hello-maven ---
[INFO] Building jar: D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-ma
ven-1.0-SNAPSHOT-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.007 s
[INFO] Finished at: 2023-10-15T11:38:57+08:00
[INFO] Final Memory: 13M/245M
[INFO] ------------------------------------------------------------------------
我们可以看到,当执行 verify生命周期阶段的时候,maven-source-plugin:jar-no-fork 会得以执行,它会创建一
个以 -sources.jar
结尾的源码文件包。
有时候,即使不通过 phase 元素配置生命周期阶段,插件目标也能够绑定到生命周期中去。例如,可以尝试删除
上述配置中的phase一行,再次执行 mvn verify,仍然可以看到 maven-source-plugin:jar-no-fork 得以执行。出
现这种现象的原因是:有很多插件的目标在编写时已经定义了默认绑定阶段。可以使用 maven-help-plugin 查看
插件详细信息,了解插件目标的默认绑定阶段。运行命令如下:
$ mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:3.2.1 -Ddetail
该命令输出对应插件的详细信息。在输出信息中,能够看到关于目标 jar-no-fork 的如下信息:
source:jar-no-fork
Description: This goal bundles all the sources into a jar archive. This
goal functions the same as the jar goal but does not fork the build and is
suitable for attaching to the build lifecycle.
Implementation: org.apache.maven.plugin.source.SourceJarNoForkMojo
Language: java
Bound to phase: package
Available parameters:
archive
The archive configuration to use. See Maven Archiver Reference.
attach (Default: true)
User property: attach
Specifies whether or not to attach the artifact to the project
excludeResources (Default: false)
User property: source.excludeResources
Specifies whether or not to exclude resources from the sources-jar. This
can be convenient if your project includes large resources, such as
images, and you don't want to include them in the sources-jar.
excludes
List of files to exclude. Specified as fileset patterns which are
relative to the input directory whose contents is being packaged into the
JAR.
finalName (Default: ${project.build.finalName})
The filename to be used for the generated archive file. For the
source:jar goal, '-sources' is appended to this filename. For the
source:test-jar goal, '-test-sources' is appended.
forceCreation (Default: false)
User property: source.forceCreation
Whether creating the archive should be forced. If set to true, the jar
will always be created. If set to false, the jar will only be created
when the sources are newer than the jar.
includePom (Default: false)
User property: source.includePom
Specifies whether or not to include the POM file in the sources-jar.
includes
List of files to include. Specified as fileset patterns which are
relative to the input directory whose contents is being packaged into the
JAR.
outputDirectory (Default: ${project.build.directory})
The directory where the generated archive file will be put.
useDefaultExcludes (Default: true)
Exclude commonly excluded files such as SCM configuration. These are
defined in the plexus FileUtils.getDefaultExcludes()
useDefaultManifestFile (Default: false)
Set this to true to enable the use of the defaultManifestFile.
该输出包含了一段关于 jar-no-fork 目标的描述,这里关心的是 Bound to phase 这一项,它表示该目标默认绑定
的生命周期阶段(这里是 package)。也就是说,当用户配置使用 maven-source-plugin 的 jar-no-fork 目标的时
候,如果不指定 phase 参数,该目标就会被绑定到 package 阶段。
我们知道,当插件目标被绑定到不同的生命周期阶段的时候,其执行顺序会由生命周期阶段的先后顺序决定。如果
多个目标被绑定到同一个阶段,它们的执行顺序会是怎样?
答案很简单,当多个插件目标绑定到同一个阶段的时候,这些插件声明的先后顺序决定了目标的执行顺序。
完成了插件和生命周期的绑定之后,用户还可以配置插件目标的参数,进一步调整插件目标所执行的任务,以满足
项目的需求。几乎所有 Maven 插件的目标都有一些可配置的参数,用户可以通过命令行和 POM 配置等方式来配
置这些参数。
在日常的 Maven 使用中,我们会经常从命令行输入并执行 Maven 命令。在这种情况下,如果能够方便地更改某
些插件的行为,无疑会十分方便。很多插件目标的参数都支持从命令行配置,用户可以在 Maven 命令中使用 -D
参数,并伴随一个参数键=参数值的形式,来配置插件目标的参数。
例如,maven-surefire-plugin 提供了一个 maven.test.skip 参数,当其值为 true 的时候,就会跳过执行测试。于
是,在运行命令的时候,加上如下 -D 参数就能跳过测试:
$ mvn install -Dmaven.test.skip=true
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ hello-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-maven ---
[INFO] Not copying test resources
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ hello-maven ---
[INFO] Not compiling test sources
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-maven ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-maven ---
[INFO]
[INFO] --- maven-shade-plugin:3.2.4:shade (default) @ hello-maven ---
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar with D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-1.0-SNAPSHOT-shaded.jar
[INFO]
[INFO] --- maven-source-plugin:3.2.1:jar-no-fork (attach-sources) @ hello-maven ---
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ hello-maven ---
[INFO] Installing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar to D:\DecompressionSoftwareInstall\apache-maven-3.3.9-bin\repository\org\example\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHOT.jar
[INFO] Installing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\pom.xml to D:\DecompressionSoftwareInstall\apache-maven-3.3.9-bin\repository\org\example\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHOT.pom
[INFO] Installing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-1.0-SNAPSHOT-sources.jar to D:\DecompressionSoftwareInstall\apache-maven-3.3.9-bin\repository\org\example\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHOT-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.161 s
[INFO] Finished at: 2023-10-15T13:36:02+08:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------
参数 -D 是 Java 自带的,其功能是通过命令行设置一个Java 系统属性,Maven 简单地重用了该参数,在准备插件
的时候检查系统属性,便实现了插件参数的配置。
并不是所有的插件参数都适合从命令行配置,有些参数的值从项目创建到项目发布都不会改变,或者说很少改变,
对于这种情况,在POM文件中一次性配置就显然比重复在命令行输人要方便。
用户可以在声明插件的时候,对此插件进行一个全局的配置。也就是说,所有该基于该插件目标的任务,都会使用
这些配置。例如,我们通常会需要配置 maven-compiler-plugin 告诉它编译 Java 1.8 版本的源文件,生成与
JVM1.8 兼容的字节码文件。
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.10.1version>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
这样,不管绑定到 compile 阶段的 maven-compiler-plugin:compile 任务,还是绑定到test-compiler 阶段的
maven-compiler-plugin:testCompiler 任务,就都能够使用该配置,基于 Java 1.5 版本进行编译。
除了为插件配置全局的参数,用户还可以为某个插件任务配置特定的参数。以 maven-antrun-plugin 为例,它有
一个目标run,可以用来在 Maven 中调用 Ant 任务。用户将 maven-antrun-plugin:run 绑定到多个生命周期阶段
上,再加以不同的配置,就可以让 Maven 在不同的生命阶段执行不同的任务。
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-antrun-pluginartifactId>
<version>1.8version>
<executions>
<execution>
<id>ant-validateid>
<phase>validatephase>
<goals>
<goal>rungoal>
goals>
<configuration>
<tasks>
<echo>I'm bound to validate phase.echo>
tasks>
configuration>
execution>
<execution>
<id>ant-verifyid>
<phase>verifyphase>
<goals>
<goal>rungoal>
goals>
<configuration>
<tasks>
<echo>I'm bound to verify phase.echo>
tasks>
configuration>
execution>
executions>
plugin>
在上述代码片段中,首先,maven-antrun-plugin:run 与 validate 阶段绑定,从而构成一个 id 为 ant-validate
的任务。插件全局配置中的 configuration元素位于 plugin元素下面,而这里的 configuration 元素则位于
execution元素下,表示这是特定任务的配置,而非插件整体的配置。这个ant-validate任务配置了一个echo Ant
任务,向命令行输出一段文字,表示该任务是绑定到 validate 阶段的。第二个任务的id为 ant-verify,它绑定到了
verify 阶段,同样它也输出一段文字到命令行,告诉该任务绑定到了 verify 阶段。
$ mvn verify
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-antrun-plugin:1.8:run (ant-validate) @ hello-maven ---
[WARNING] Parameter tasks is deprecated, use target instead
[INFO] Executing tasks
main:
[echo] I'm bound to validate phase.
[INFO] Executed tasks
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ hello-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-maven ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ hello-maven ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-maven ---
[INFO] Surefire report directory: D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.apache.HelloWorldTest
init
Tests run: 2, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.047 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-maven ---
[INFO]
[INFO] --- maven-shade-plugin:3.2.4:shade (default) @ hello-maven ---
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar with D:\zhangshixing\hexo\website-hexo-theme-particlex\source\_posts\Maven\code\Maven实战-声明周期和插件\HelloMaven\target\hello-maven-1.0-SNAPSHOT-shaded.jar
[INFO]
[INFO] --- maven-source-plugin:3.2.1:jar-no-fork (attach-sources) @ hello-maven ---
[INFO]
[INFO] --- maven-antrun-plugin:1.8:run (ant-verify) @ hello-maven ---
[WARNING] Parameter tasks is deprecated, use target instead
[INFO] Executing tasks
main:
[echo] I'm bound to verify phase.
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.442 s
[INFO] Finished at: 2023-10-15T13:45:33+08:00
[INFO] Final Memory: 15M/215M
[INFO] ------------------------------------------------------------------------
仅仅理解如何配置使用插件是不够的。当遇到一个构建任务的时候,用户还需要知道去哪里寻找合适的插件,以帮
助完成任务。找到正确的插件之后,还要详细了解该插件的配置点。由于Maven 的插件非常多,而且这其中的大
部分没有完善的文档,因此,使用正确的插件并进行正确的配置,其实并不是一件容易的事。
基本上所有主要的 Maven 插件都来自 Apache 和 Codehaus。由于 Maven 本身是属于 Apache 软件基金会的,
因此它有很多官方的插件,每天都有成千上万的 Maven 用户在使用这些插件,它们具有非常好的稳定性。详细的
列表可以在这个地址得到:https://maven.apache.org/plugins/index.html
单击某个插件的链接便可以得到进一步的信息。
所有官方插件能在这里下载:https://repo1.maven.org/maven2/org/apache/maven/plugins/
。
除了 Apache 上的官方插件之外,托管于 Codehaus上的 Mojo 项目也提供了大量了 Maven插件,详细的列表可
以访问:http://mojo.codehaus.org/plugins.html
。需要注意的是,这些插件的文档和可靠性相对较差,在
使用时,如果遇到问题,往往只能自己去看源代码。所有 Codehaus 的 Maven 插件能在这里下载:
http://repository.codehaus.org/org/codehaus/mojo/
由于上述两个站点提供的插件非常多,而实际使用中常用的插件远不会是这个数量,因此附录归纳了一些比较常用
的插件。
虽然并非所有插件都提供了完善的文档,但一些核心插件的文档还是非常丰富的。以 maven-surefire-plugin 为
例,访问 http://maven.apache.org/plugins/maven-surefire-plugin/
可以看到该插件的简要介绍、包含
的目标、使用介绍、FAQ 以及很多实例。
一般来说,通过阅读插件文档中的使用介绍和实例,就应该能够在自己的项目中很好地使用该插件。但当我们想了
解非常细节的目标参数时,就需要进一步访问该插件每个目标的文档。以 maven-surefire-plugin 为例,可以通过
在命令行传人 maven.test.skip 参数来跳过测试执行,而执行测试的插件目标是 surefire:test,访问其文档:
http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html
,可以找到目标参数 skip。
文档详细解释了该参数的作用、类型等信息。基于该信息,用户可以在POM中配置 maven-surefire-plugin 的
skip 参数为 true来跳过测试。这个时候读者可能会不理解了,之前在命令行传入的参数不是 maven.test.skip吗?
的确如此,虽然对于该插件目标的作用是一样的,但从命令行传人的参数确实不同于该插件目标的参数名称。命令
行参数是由该插件参数的表达式(Expression)决定的。可以看到,surefire:test skip参数的表达式为
${maven.test.skip}
,它表示可以在命令行以 -Dmaven.test.skip=true
的方式配置该目标。并不是所有
插件目标参数都有表达式,也就是说,一些插件目标参数只能在POM中配置。
除了访问在线的插件文档之外,还可以借助 maven-help-plugin 来获取插件的详细信息。
可以运行如下命令来获取 maven-compiler-plugin 3.10.1 版本的信息:
$ mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin:3.10.1
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 109, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.3.0:describe (default-cli) @ hello-maven ---
[INFO] org.apache.maven.plugins:maven-compiler-plugin:3.10.1
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.10.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
compiler:help
Description: Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display
parameter details.
compiler:testCompile
Description: Compiles application test sources.
For more information, run 'mvn help:describe [...] -Ddetail'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.921 s
[INFO] Finished at: 2023-10-15T17:17:19+08:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------
这里执行的是 maven-help-plugin 的 describe 目标,在参数 plugin 中输入需要描述插件的 groupId、artifactld
和 version。Maven 在命令行输出 maven-compiler-plugin 的简要信息,包括该插件的坐标、目标前缀和目标
等。
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.10.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
compiler:help
Description: Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display
parameter details.
compiler:testCompile
Description: Compiles application test sources.
For more information, run 'mvn help:describe [...] -Ddetail'
对于坐标和插件目标,不再多做解释,这里值得一提的是目标前缀(Goal Prefix),其作用是方便在命令行直接运行
插件。maven-compiler-plugin 的目标前缀是 compiler。
在描述插件的时候,还可以省去版本信息,让Maven 自动获取最新版本来进行表述。
例如:
$ mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 109, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.3.0:describe (default-cli) @ hello-maven ---
[INFO] org.apache.maven.plugins:maven-compiler-plugin:3.10.1
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.10.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
compiler:help
Description: Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display
parameter details.
compiler:testCompile
Description: Compiles application test sources.
For more information, run 'mvn help:describe [...] -Ddetail'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.949 s
[INFO] Finished at: 2023-10-15T17:20:38+08:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------
进一步简化,可以使用插件目标前缀替换坐标。例如:
$ mvn help:describe -Dplugin=compiler
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 109, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.3.0:describe (default-cli) @ hello-maven ---
[INFO] org.apache.maven.plugins:maven-compiler-plugin:3.10.1
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.10.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
compiler:help
Description: Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display
parameter details.
compiler:testCompile
Description: Compiles application test sources.
For more information, run 'mvn help:describe [...] -Ddetail'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.937 s
[INFO] Finished at: 2023-10-15T17:21:39+08:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------
如果想仅仅描述某个插件目标的信息,可以加上 goal 参数:
$ mvn help:describe -Dplugin=compiler -Dgoal=compile
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 109, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.3.0:describe (default-cli) @ hello-maven ---
[INFO] Mojo: 'compiler:compile'
compiler:compile
Description: Compiles application sources
For more information, run 'mvn help:describe [...] -Ddetail'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.822 s
[INFO] Finished at: 2023-10-15T17:23:19+08:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------
如果想让 maven-help-plugin 输出更详细的信息,可以加上detail 参数:
$ mvn help:describe -Dplugin=compiler -Ddetail
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 109, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.3.0:describe (default-cli) @ hello-maven ---
[INFO] org.apache.maven.plugins:maven-compiler-plugin:3.10.1
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.10.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
Implementation: org.apache.maven.plugin.compiler.CompilerMojo
Language: java
Bound to phase: compile
Available parameters:
annotationProcessorPaths
Classpath elements to supply as annotation processor path. If specified,
the compiler will detect annotation processors only in those classpath
elements. If omitted, the default classpath is used to detect annotation
processors. The detection itself depends on the configuration of
annotationProcessors.
Each classpath element is specified using their Maven coordinates
(groupId, artifactId, version, classifier, type). Transitive dependencies
are added automatically. Example:
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.sample</groupId>
<artifactId>sample-annotation-processor</artifactId>
<version>1.2.3</version>
</path>
<!-- ... more ... -->
</annotationProcessorPaths>
</configuration>
annotationProcessors
Names of annotation processors to run. Only applies to JDK 1.6+ If not
set, the default annotation processors discovery process applies.
......
source (Default: 1.7)
User property: maven.compiler.source
The -source argument for the Java compiler.
NOTE: Since 3.8.0 the default value has changed from 1.5 to 1.6. Since
3.9.0 the default value has changed from 1.6 to 1.7
staleMillis (Default: 0)
User property: lastModGranularityMs
Sets the granularity in milliseconds of the last modification date for
testing whether a source needs recompilation.
target (Default: 1.7)
User property: maven.compiler.target
The -target argument for the Java compiler.
NOTE: Since 3.8.0 the default value has changed from 1.5 to 1.6. Since
3.9.0 the default value has changed from 1.6 to 1.7
useIncrementalCompilation (Default: true)
User property: maven.compiler.useIncrementalCompilation
to enable/disable incremental compilation feature.
This leads to two different modes depending on the underlying compiler.
The default javac compiler does the following:
- true (default) in this mode the compiler plugin determines whether any
JAR files the current module depends on have changed in the current
build run; or any source file was added, removed or changed since the
last compilation. If this is the case, the compiler plugin recompiles
all sources.
- false (not recommended) this only compiles source files which are newer
than their corresponding class files, namely which have changed since
the last compilation. This does not recompile other classes which use
the changed class, potentially leaving them with references to methods
that no longer exist, leading to errors at runtime.
verbose (Default: false)
User property: maven.compiler.verbose
Set to true to show messages about what the compiler is doing.
compiler:help
Description: Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display
parameter details.
Implementation: org.apache.maven.plugin.compiler.HelpMojo
Language: java
Available parameters:
detail (Default: false)
User property: detail
If true, display all settable properties for each goal.
goal
User property: goal
The name of the goal for which to show help. If unspecified, all goals
will be displayed.
indentSize (Default: 2)
User property: indentSize
The number of spaces per indentation level, should be positive.
lineLength (Default: 80)
User property: lineLength
The maximum length of a display line, should be positive.
compiler:testCompile
Description: Compiles application test sources.
Implementation: org.apache.maven.plugin.compiler.TestCompilerMojo
Language: java
Bound to phase: test-compile
Available parameters:
annotationProcessorPaths
Classpath elements to supply as annotation processor path. If specified,
the compiler will detect annotation processors only in those classpath
elements. If omitted, the default classpath is used to detect annotation
processors. The detection itself depends on the configuration of
annotationProcessors.
Each classpath element is specified using their Maven coordinates
(groupId, artifactId, version, classifier, type). Transitive dependencies
are added automatically. Example:
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.sample</groupId>
<artifactId>sample-annotation-processor</artifactId>
<version>1.2.3</version>
</path>
<!-- ... more ... -->
</annotationProcessorPaths>
</configuration>
annotationProcessors
Names of annotation processors to run. Only applies to JDK 1.6+ If not
set, the default annotation processors discovery process applies.
compilerArgs
Sets the arguments to be passed to the compiler.
Note that -J options are only passed through if fork is set to true.
Example:
<compilerArgs>
<arg>-Xmaxerrs</arg>
<arg>1000</arg>
<arg>-Xlint</arg>
<arg>-J-Duser.language=en_us</arg>
</compilerArgs>
compilerArgument
Sets the unformatted single argument string to be passed to the compiler.
To pass multiple arguments such as -Xmaxerrs 1000 (which are actually two
arguments) you have to use compilerArguments.
This is because the list of valid arguments passed to a Java compiler
varies based on the compiler version.
Note that -J options are only passed through if fork is set to true.
compilerArguments
Sets the arguments to be passed to the compiler (prepending a dash).
This is because the list of valid arguments passed to a Java compiler
varies based on the compiler version.
Note that -J options are only passed through if fork is set to true.
To pass -Xmaxerrs 1000 -Xlint -Xlint:-path -Averbose=true you should
include the following:
<compilerArguments>
<Xmaxerrs>1000</Xmaxerrs>
<Xlint/>
<Xlint:-path/>
<Averbose>true</Averbose>
</compilerArguments>
Deprecated. use {@link #compilerArgs} instead.
compilerId (Default: javac)
User property: maven.compiler.compilerId
The compiler id of the compiler to use. See this guide for more
information.
......
testTarget
User property: maven.compiler.testTarget
The -target argument for the test Java compiler.
useIncrementalCompilation (Default: true)
User property: maven.compiler.useIncrementalCompilation
to enable/disable incremental compilation feature.
This leads to two different modes depending on the underlying compiler.
The default javac compiler does the following:
- true (default) in this mode the compiler plugin determines whether any
JAR files the current module depends on have changed in the current
build run; or any source file was added, removed or changed since the
last compilation. If this is the case, the compiler plugin recompiles
all sources.
- false (not recommended) this only compiles source files which are newer
than their corresponding class files, namely which have changed since
the last compilation. This does not recompile other classes which use
the changed class, potentially leaving them with references to methods
that no longer exist, leading to errors at runtime.
verbose (Default: false)
User property: maven.compiler.verbose
Set to true to show messages about what the compiler is doing.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.986 s
[INFO] Finished at: 2023-10-15T17:25:43+08:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------
读者可以在实际环境中使用 help:describe 描述一些常用插件的信息,以得到更加直观的感受。
如果在命令行运行 mvn -h 来显示mvn命令帮助,就可以看到如下的信息:
usage:mvn [options][<goal(s)>][<phase(s)>]
Options:
...
该信息告诉了我们 mvn 命令的基本用法,options表示可用的选项,mvn命令有20 多个选项,这里暂不详述,读
者可以根据说明来了解每个选项的作用。除了选项之外,mvn命令后面可以添加一个或者多个goal 和 phase,它
们分别是指插件目标和生命周期阶段。前面已经详细介绍了如何通过该参数控制 Maven 的生命周期。现在我们关
心的是另外一个参数:goal。
我们知道,可以通过mvn命令激活生命周期阶段,从而执行那些绑定在生命周期阶段上的插件目标。但 Maven 还
支持直接从命令行调用插件日标。Maven 支持这种方式是因为有些任务不适合绑定在生命周期上,例如
maven-help-plugin:describe,我们不需要在构建项目的时候去描述插件信息,又如
maven-dependency-plugin:tree,我们也不需要在构建项目的时候去显示依赖树。因此这些插件目标应该通过如
下方式使用:
$ mvn help:describe -Dplugin=compiler
$ mvn dependency:tree
不过,这里还有一个疑问,describe是 maven-help-plugin 的目标没错,但冒号前面的help是什么呢?它既不是
groupld,也不是artifactld,Maven 是如何根据该信息找到对应版本插件的呢?同理,为什么不是
maven-dependency-plugin:tree,而是 dependency:tree?
解答该疑问之前,可以先尝试一下如下的命令:
$ mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:describe -Dplugin=compiler
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.2.0:describe (default-cli) @ hello-maven ---
[INFO] org.apache.maven.plugins:maven-compiler-plugin:3.10.1
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.10.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
compiler:help
Description: Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display
parameter details.
compiler:testCompile
Description: Compiles application test sources.
For more information, run 'mvn help:describe [...] -Ddetail'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.939 s
[INFO] Finished at: 2023-10-15T17:37:39+08:00
[INFO] Final Memory: 12M/309M
[INFO] ------------------------------------------------------------------------
$ mvn org.apache.maven.plugins:maven-dependency-plugin:3.2.0:tree
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for org.example:hello-maven:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-compiler-plugin @ line 69, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:3.2.0:tree (default-cli) @ hello-maven ---
[INFO] org.example:hello-maven:jar:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.13.2:test
[INFO] \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.871 s
[INFO] Finished at: 2023-10-15T17:38:53+08:00
[INFO] Final Memory: 15M/309M
[INFO] ------------------------------------------------------------------------
这两条命令就比较容易理解了,插件的 groupld、artifactId、version以及goal都得以清晰描述。它们的效果与之
前的两条命令基本是一样的,但显然前面的命令更简洁,更容易记忆和使用。为了达到该目的,Maven 引入了目
标前缀的概念,help 是 maven-help-plugin 的目标前缀,dependency 是 maven-dependency-plugin 的前缀,
有了插件前缀,Maven 就能找到对应的 artifactld。不过,除了 artifactld,Maven 还需要得到 groupId 和
version 才能精确定位到某个插件。
为了方便用户使用和配置插件,Maven 不需要用户提供完整的插件坐标信息,就可以解析得到正确的插件,
Maven 的这一特性是一把双刃剑,虽然它简化了插件的使用和配置,可一旦插件的行为出现异常,用户就很难快
速定位到出问题的插件构件。例如 mvn help:system 这样一条命令,它到底执行了什么插件?该插件的 groupId、
artifactld 和version 分别是什么?这个构件是从哪里来的?本节就详细介绍 Maven的运行机制,以让读者不仅知其
然,更知其所以然。
与依赖构件一样,插件构件同样基于坐标存储在 Maven 仓库中。在需要的时候,Maven 会从本地仓库寻找插
件,如果不存在,则从远程仓库查找。找到插件之后,再下载到本地仓库使用。
值得一提的是,Maven会区别对待依赖的远程仓库与插件的远程仓库,前面介绍了如何配置远程仓库,但那种配
置只对一般依赖有效果。当 Maven 需要的依赖在本地仓库不存在时,它会去所配置的远程仓库查找,可是当
Maven 需要的插件在本地仓库不存在时,它就不会去这些远程仓库查找。
不同于,repositories 及其 repository 子元素,插件的远程仓库使用 pluginRepositories 和 pluginRepository 配
置。例如,Maven 内置了如下的插件远程仓库配置。
<pluginRepositories>
<pluginRepository>
<id>centralid>
<name>Maven Plugin Repositoryname>
<url>https://repo1.maven.org/maven2/url>
<layout>defaultlayout>
<snapshots>
<enabled>falseenabled>
snapshots>
<releases>
<updatePolicy>neverupdatePolicy>
releases>
pluginRepository>
pluginRepositories>
除了 pluginRepositories 和 pluginRepository 标签不同之外,其余所有子元素表达的含义与前面所介绍的依赖远
程仓库配置完全一样。我们甚至看到,这个默认插件仓库的地址就是中央仓库,它关闭了对SNAPSHOT的支持,
以防止引入SNAPSHOT版本的插件而导致不稳定的构建。
一般来说,中央仓库所包含的插件完全能够满足我们的需要,因此也不需要配置其他的插件仓库。只有在很少的情
况下,项目使用的插件无法在中央仓库找到,或者自己编写了插件,这个时候可以参考上述的配置,在 POM 或者
settings.xml 中加人其他的插件仓库配置。
在POM中配置插件的时候,如果该插件是 Maven 的官方插件(即如果其 groupld 为
org.apache.maven.plugins),就可以省略 groupld配置。
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.10.1version>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
上述配置中省略了 maven-compiler-plugin 的 groupld,Maven 在解析该插件的时候,会自动用默认 groupld
org.apache. maven. plugins 补齐。
笔者不推荐使用 Maven 的这一机制,虽然这么做可以省略一些配置,但这样的配置会让团队中不熟悉Maven的成
员感到费解,况且能省略的配置也就仅仅一行而已。
同样是为了简化插件的配置和使用,在用户没有提供插件版本的情况下,Maven 会自动解析插件版本。
首先,Maven在超级POM中为所有核心插件设定了版本,超级POM是所有Maven项目的父 POM,所有项目都继
承这个超级 POM 的配置,因此,即使用户不加任何配置,Maven 使用核心插件的时候,它们的版本就已经确定
了。这些插件包括 maven-clean-plugin、maven-compiler-plugin、maven-surefire-plugin等。
如果用户使用某个插件时没有设定版本,而这个插件又不属于核心插件的范畴,Maven 就会去检查所有仓库中可
用的版本,然后做出选择。前面介绍的仓库元数据 groupId/artifactld/maven-metadata.xml
。
以 maven-compiler-plugin 为例,它在中央仓库的仓库元数据为
http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml
其内容见代码:
<metadata>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<versioning>
<latest>3.11.0latest>
<release>3.11.0release>
<versions>
<version>2.0-beta-1version>
<version>2.0version>
<version>2.0.1version>
<version>2.0.2version>
<version>2.1version>
<version>2.2version>
<version>2.3version>
<version>2.3.1version>
<version>2.3.2version>
<version>2.4version>
<version>2.5version>
<version>2.5.1version>
<version>3.0version>
<version>3.1version>
<version>3.2version>
<version>3.3version>
<version>3.5version>
<version>3.5.1version>
<version>3.6.0version>
<version>3.6.1version>
<version>3.6.2version>
<version>3.7.0version>
<version>3.8.0version>
<version>3.8.1version>
<version>3.9.0version>
<version>3.10.0version>
<version>3.10.1version>
<version>3.11.0version>
versions>
<lastUpdated>20230227075825lastUpdated>
versioning>
metadata>
Maven 遍历本地仓库和所有远程插件仓库,将该路径下的仓库元数据归并后,就能计算出 latest 和 release 的
值。latest 表示所有仓库中该构件的最新版本,而release 表示最新的非快照版本。在Maven 2中,插件的版本会
被解析至latest。也就是说,当用户使用某个非核心插件且没有声明版本的时候,Maven 会将版本解析为所有可用
仓库中的最新版本,而这个版本也可能是快照版。
当插件的版本为快照版本时,就会出现潜在的问题。Maven 会基于更新策略,检查并使用快照的更新。某个插件
可能昨天还用得好好的,今天就出错了,其原因就是这个快照版本的插件发生了变化。为了防止这类问题,
Maven 3 调整了解析机制,当插件没有声明版本的时候,不再解析至latest,而是使用release。这样就可以避免
由于快照频繁更新而导致的插件行为不稳定。
依赖 Maven 解析插件版本其实是不推荐的做法,即使 Maven 3 将版本解析到最新的非快照版,也还是会有潜在
的不稳定性。例如,可能某个插件发布了一个新的版本,而这个版本的行为与之前的版本发生了变化,这种变化就
可能导致项目构建失败。因此,使用插件的时候,应该一直显式地设定版本,这也解释了 Maven 为什么要在超级
POM 中为核心插件设定版本。
前面讲到 mvn 命令行支持使用插件前缀来简化插件的调用,现在解释 Maven 如何根据插件前缀解析得到插件的
坐标。
插件前缀与 groupld:artifactld 是一一对应的,这种匹配关系存储在仓库数据中。与之前提到的
groupId/artifactId/maven-metadata.xml
不同,这里的仓库元数据为
groupld/maven-metadata.xml
,那么这里的 groupld 是什么呢?
前面提到主要的插件都位于 https://repo1.maven.org/maven2/org/apache/maven/plugins/
和
http://repository.codehaus.org/org/codehaus/mojo/
相应地,Maven 在解析插件仓库元数据的时候,会默认使用 org.apache.maven.plugins 和 org.codehaus.mojo
两个 groupld。也可以通过配置 settings.xml 让 Maven 检查其他groupld 上的插件仓库元数据:
<settings>
<pluginGroups>
<pluginGroup>com.your.pluginspluginGroup>
pluginGroups>
settings>
基于该配置,Maven 就不仅仅会检查 org/apache/maven/plugins/maven-metadata.xml
和
org/codehaus/mojo/maven-metadata.xml
,还会检查 com/your/plugins/maven-metadata.xml
。
下面看一下插件仓库元数据的内容,见代码。
<metadata>
<plugins>
<plugin>
<name>Maven Clean Pluginname>
<prefix>cleanprefix>
<artifactId>maven-clean-plugin
artifactId>
plugin>
<plugin>
<name>Maven Compiler Pluginname>
<prefix>compilerprefix>
<artifactId>maven-compiler-plugin
artifactId>
plugin>
<plugin>
<name>Maven Dependency Pluginname>
<prefix>dependencyprefix>
<artifactId>maven-dependency-plugin
artifactId>
plugin>
plugins>
metadata>
上述内容是从中央仓库的 org.apache.maven.plugins groupld 下插件仓库元数据中截取的一些片段,从这段数据
中就能看到 maven-clean-plugin 的前缀为 clean,maven-compiler-plugin 的前缀为 compiler,
maven-dependency-plugin 的前缀为 dependency。
当 Maven 解析到 dependency:tree 这样的命令后,它首先基于默认的 groupld 归并所有插件仓库的元数据
org/apache/maven/plugins/maven-metadata.xml
;其次检查归并后的元数据,找到对应的 artifactld 为
maven-dependency-plugin;然后结合当前元数据的 groupld org.apache. maven.plugins;最后使用上节描述
的方法解析得到 version,这时就得到了完整的插件坐标。如果
org/apache/maven/plugins/maven-metadata.xml
没有记录该插件前缀,则接着检查其他 groupld 下的元数
据,如 org/codehaus/mojo/maven-metadata.xml
,以及用户自定义的插件组。如果所有元数据中都不包含该
前缀,则报错。