当前位置: 首页 > news >正文

Maven实战.插件

文章目录

  • 插件目标
  • 插件绑定
    • 1️⃣内置绑定
    • 2️⃣自定义绑定
  • 插件配置
    • 1️⃣命令行插件配置
    • 2️⃣POM中插件全局配置
    • 3️⃣POM中插件任务配置

插件目标

在进一步详述插件和生命周期的绑定关系之前,必须先了解插件目标(PluginCoal)的概念。我们知道,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-sure-fire-plugin 的 test 目标)。

插件绑定

Maven 的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标相互绑定,以完成某个具体的构建任务。例如项目编译这一任务,它对应了 default 生命周期的 compile 这一阶段,而 maven-compiler-plugin 这一插件的 compile 目标能够完成该任务。因此,将它们绑定,就能实现项目编译的目的,如下
在这里插入图片描述

1️⃣内置绑定

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

clean 生命周期仅有 pre-clean、clean 和 post-clean 三个阶段,其中的clean 与 maven-clean-plugin : clean 绑定。maven-clean-plugin 仅有clean 这一个目标,其作用就是删除项目的输出目录。clean 生命周期阶段与插件目标的绑定关系如下表格所示。

clean 生命周期阶段与插件目标的绑定关系

生命周期阶段插件目标
pre-clean maven-clean-plugin:clean
clean
post-clean

site 生命周期有 pre-site、site、post-site 和 site-deploy 四个阶段,其中,site 和 maven-siteplugin : site 相互绑定,site-deploy 和 maven-site-plugin : depoy相互绑定。maven-site-plugin 有很多目标,其中,site 目标用来生成项目站点,deploy 目标用来将项目站点部署到远程服务器上。site 生命周期阶段与插件目标的绑定关系如下表格所示。

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 包。

由于项目的打包类型会影响构建的具体过程,因此,defaut 生命周期的阶段与插件目标的绑定关系由项目打包类型所决定,打包类型是通过 POM 中的 packaging 元素定义的。最常见、最重要的打包类型是 jar,它也是默认的打包类型。基于该打包类型的项目,其 default 生命周期的内置插件绑定关系及具体任务如下表格所示。

default 生命周期的内置插件绑定关系及具体任务(打包类型: jar)

生命周期阶段插件目标执行任务
process-resources maven-resources-plugin:resources 复制主资源文件至主输出目录
compile maven-compiler-plugin:compile 编译主代码至主输出目录
process-test-resources maven-resources-plugin:testResources 复制测试资源文件至测试输出目录
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 等。它们的 defaut 生命周期与插件目标的绑定关系可参阅 Maven 官方文档,这里不再赘述。

你也可以从 Maven 项目的命令行执行 mvn clean install 命令,看到项目在构建过程中执行了哪些插件目标。

2️⃣自定义绑定

除了内置绑定以外,用户还能够自己选择将某个插件目标绑定到生命周期的某个阶段上,这种自定义绑定方式能让 Maven 项目在构建过程中执行更多更富特色的任务。

一个常见的例子是创建项目的源码 jar 包,内置的插件绑定关系中并没有涉及这一任务,因此需要用户自行配置。maven-source-plugin 可以帮助我们完成该任务,它的 jar-no-fork 目标能够将项目的主代码打包成iar 文件,可以将其绑定到 default 生命周期的 verify 阶段上、在执行完集成测试后和安装构件之前创建源码 jar 包。具体配置见如下代码:

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

在 POM 的 build 元素下的 plugins 子元素中声明插件的使用,该例中用到的是 maven-scurce-plugin,其 groupId 为org:apache.maven.plugins,这也是 Maven 官方插件的 groupId,紧接着 artifactld 为 maven-source-plugin,version 为 2.2.1。对于自定义绑定的插件,用户总是应该声明一个非快照版本,这样可以避免由于插件版本变化造成的构建不稳定性。

上述配置中,除了基本的插件坐标声明外,还有插件执行配置,executions 下每个 execution 子元素可以用来配置执行一个任务。该例中配置了一个 id 为 attach-sources 的任务通过 phase 配置,将其绑定到 verify 生命周期阶段上,再通过 goals 配置指定要执行的插件目标。至此,自定义插件绑定完成。运行 mvn verify 就能看到如下输出:

[INFO] --- source:2.2.1:jar-no-fork (attach-sources) @ hello-world ---
[INFO] Building jar: D:\Work\gittest\demo-maven-practical\hello-world\target\hello-world-1.0-SNAPSHOT-sources.jar

我们可以看到,当执行 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-forkDescription: This goal bundles all the sources into a jar archive. Thisgoal functions the same as the jar goal but does not fork the build and issuitable for attaching to the build lifecycle.Implementation: org.apache.maven.plugin.source.SourceJarNoForkMojoLanguage: javaBound to phase: packageAvailable parameters:
...

该输出包含了一段关于 jar-no-fork 目标的描述,这里关心的是 Bound to phase 这一项,它表示该目标默认绑定的生命周期阶段(这里是package)。也就是说,当用户配置使用 maven-source-plugin 的 jar-no-fork 目标的时候,如果不指定 phase 参数,该目标就会被绑定到 package Maven 生命周期 default周期 的 package 阶段。

当插件目标被绑定到不同的生命周期阶段的时候,其执行顺序会由生命周期阶段的先后顺序决定。如果多个目标被绑定到同一个阶段,它们的执行顺序会是怎样?答案很简单,当多个插件目标绑定到同一个阶段的时候,这些插件声明的先后顺序决定了目标的执行顺序。

插件配置

完成了插件和生命周期的绑定之后,用户还可以配置插件目标的参数,进一步调整插件目标所执行的任务,以满足项目的需求。几乎所有 Maven 插件的目标都有一些可配置的参数,用户可以通过命令行和 POM 配置等方式来配置这些参数。

1️⃣命令行插件配置

在日常的 Maven 使用中,我们会经常从命令行输入并执行 Maven 命令。在这种情况下如果能够方便地更改某些插件的行为,无疑会十分方便。很多插件目标的参数都支持从命令行配置,用户可以在 Maven 命令中使用 -D 参数,并伴随一个参数键=参数值的形式,来配置插件目标的参数。

例如,maven-surefire-plugin 提供了一个 maven.test.skip 参数,当其值为 true 的时候,就会跳过执行测试。于是,在运行命令的时候,加上如下 -D 参数就能跳过测试:

 mvn install -Dmaven.test.skip=true

参数- D 是 Java 自带的,其功能是通过命令行设置一个 Java 系统属性,Maven 简单地重用了该参数,在准备插件的时候检查系统属性,便实现了插件参数的配置。

2️⃣POM中插件全局配置

并不是所有的插件参数都适合从命令行配置,有些参数的值从项目创建到项目发布都不会改变,或者说很少改变,对于这种情况,在 POM 文件中一次性配置就显然比重复在命令行输入要方便。

用户可以在声明插件的时候,对此插件进行一个全局的配置。也就是说,所有该基于该插件目标的任务,都会使用这些配置。例如,我们通常会需要配置 maven-compiler-plugin 告诉它编译 Java 1.5 版本的源文件,生成与 JVM1.5 兼容的字节码文件,见代码如下:

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

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

插件全局配置元素是 configuration 元素。

3️⃣POM中插件任务配置

除了为插件配置全局的参数,用户还可以为某个插件任务配置特定的参数。以 maven-antrumn-plugin 为例,它有一个目标 run,可以用来在 Maven 中调用 Ant 任务。用户将 maven-antrun-plugin:run 绑定到多个生命周期阶段上,再加以不同的配置,就可以让 Maven 在不同的生命阶段执行不同的任务,如下:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><version>1.8</version><executions><execution><id>ant-validate</id><phase>validate</phase><goals><goal>run</goal></goals><configuration><tasks><echo>i am 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 am bound to verify phase</echo></tasks></configuration></execution></executions>
</plugin>

在上述代码片段中,首先,maven-antrun-plugin:run 与 validate 阶段绑定,从而构成一个 id 为 ant-validate 的任务。插件全局配置中的 configuration 元素位于 plugin 元素下面,而这里的 confguration 元素则位于 execution 元素下,表示这是特定任务的配置,而非插件整体的配置。这个 ant-validate 任务配置了一个echo Ant 任务,向命令行输出一段文字,表示该任务是绑定到 validate 阶段的。第二个任务的 id 为 ant-verify,它绑定到了 verify 阶段,同样它也输出一段文字到命令行,告诉该任务绑定到了verify 阶段。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 深入SpringBoot:SpringCache的集成与使用
  • SQL注入之sqli-labs靶场第一关
  • sql server 通过 sql查询今天、本周、上周、本月、上月、今年、去年的时间范围
  • forwardRef和useImperativeHandle到底能做啥
  • DataWhale AI夏令营-英特尔-阿里天池LLM Hackathon
  • Xlua原理分析 四
  • 虚拟机ubuntu22.04找不到ttyUSB*端口
  • Windows系统之环境变量
  • Lumos学习王佩丰Excel第十讲:Sumif函数
  • .NET未来路在何方?
  • ei会议论文是什么级别
  • 登录相关功能的优化【JWT令牌+拦截器+跨域】
  • 研0 冲刺算法竞赛 day27 P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
  • linux 进程 inode 信息获取
  • Java 面试常见问题之——final,finalize 和 finally 的不同之处
  • CSS实用技巧干货
  • Java IO学习笔记一
  • JS字符串转数字方法总结
  • PaddlePaddle-GitHub的正确打开姿势
  • Protobuf3语言指南
  • Python利用正则抓取网页内容保存到本地
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • Vue2.0 实现互斥
  • windows下如何用phpstorm同步测试服务器
  • 给新手的新浪微博 SDK 集成教程【一】
  • 类orAPI - 收藏集 - 掘金
  • 面试遇到的一些题
  • 全栈开发——Linux
  • 我是如何设计 Upload 上传组件的
  • 你对linux中grep命令知道多少?
  • 仓管云——企业云erp功能有哪些?
  • 扩展资源服务器解决oauth2 性能瓶颈
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #stm32整理(一)flash读写
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (Java入门)抽象类,接口,内部类
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (二)linux使用docker容器运行mysql
  • (二)学习JVM —— 垃圾回收机制
  • (回溯) LeetCode 40. 组合总和II
  • (利用IDEA+Maven)定制属于自己的jar包
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)人的集合论——移山之道
  • . NET自动找可写目录
  • .apk 成为历史!
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • @Pointcut 使用
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [ 转载 ] SharePoint 资料
  • [000-002-01].数据库调优相关学习