介绍
Maven 插件可以用 Java 或多种脚本语言中的任何一种编写。插件由一个或多个 Mojo 组成,每个 Mojo 都是插件目标之一的实现。Maven 试图通过其新的 Mojo API 避开程序员的障碍。这为许多 Mojos 在 Maven 之外重用或从 Ant 等外部系统桥接到 Maven 提供了机会。
注意:目前,我们将讨论限制在基于 Java 的 Mojos,因为每种脚本语言都会以不同的实现形式呈现这些相同的基本要求。
尽管设计对 Mojos 的要求非常低,但 Mojo 开发人员仍然必须牢记一些要求。基本上,这些 Mojo 需求由
org.apache.maven.plugin.Mojo
Mojo 必须实现的接口体现(或者扩展其抽象基类对应物
org.apache.maven.plugin.AbstractMojo
)。这个接口保证了 Mojo 的正确执行契约:无参数、void 返回类型和只允许的 throws 子句
org.apache.maven.plugin.MojoExecutionException
及其派生词。它还保证 Mojo 可以访问标准的 Maven 用户反馈机制,
org.apache.maven.plugin.logging.Log
因此 Mojo 可以将重要事件传达给控制台或其他日志接收器。
如前所述,每个插件 - 或封装的 Mojos 集 - 必须提供一个
在插件 jar 文件内plugin.xml
的路径下
调用的描述符。META-INF/maven
幸运的是,Maven 还提供了一组 Javadoc 注释(名为Mojo Javadoc Tags)、Java 5 注释(名为Maven Plugin Tools Java5 Annotations)和工具(名为plugin-tools)来生成这个描述符,因此开发人员不必担心直接创作或维护单独的 XML 元数据文件。
为了作为开发人员的快速参考,本页面的其余部分将记录这些被认为是开发 Mojos 的最佳实践的特性(API 以及注释)。
API 文档
org.apache.maven.plugin.Mojo
这个接口形成了 Mojos 与 Maven 基础设施交互所需的契约。它具有一种
execute()
触发 Mojo 的构建过程行为的方法,并且
MojoExecutionException
如果发生错误条件可以抛出一个。有关正确使用此类的讨论,请参见下文
Exception
。还包括该
setLog(..)
方法,它仅允许 Maven 注入一个日志机制,该机制将允许 Mojo 通过标准 Maven 通道与外部世界通信。
方法总结:
-
void setLog( org.apache.maven.plugin.logging.Log )
注入一个标准的 Maven 日志机制,以允许这个 Mojo 向用户传达事件和反馈。
-
void execute() throws org.apache.maven.plugin.MojoExecutionException
执行此 Mojo 实现的任何构建过程行为。这是 Maven 系统内 Mojo 的主要触发器,并允许 Mojo 通过抛出
MojoExecutionException
.MojoExecutionException
应该非常小心地处理(以及 Mojo 中的所有错误情况)。 严格不鼓励在不提供任何用户友好的可能原因指示的情况下简单地包装较低级别的异常。事实上,更好的做法是为 Mojo 执行中的每个连贯步骤提供错误处理代码(try/catch 节)。然后,开发人员可以更好地诊断任何错误的原因,并在MojoExecutionException
.
org.apache.maven.plugin.AbstractMojo
目前,这个抽象基类只负责管理 Maven 日志以进行具体派生。为了与此保持一致,它提供了一种
protected
方法
getLog():Log
来提供对这些具体实现的日志访问。
方法总结:
-
public void setLog( org.apache.maven.plugin.logging.Log )
[实施的]
注入一个标准的 Maven 日志机制,以允许这个 Mojo 向用户传达事件和反馈。
-
protected Log getLog()
[实施的]
提供对在此基类中管理的标准 Maven 日志记录机制的访问。
-
void execute() throws org.apache.maven.plugin.MojoExecutionException
[抽象的]
执行此 Mojo 实现的任何构建过程行为。
Mojo
有关更多信息, 请参阅上面的文档 。
org.apache.maven.plugin.logging.Log
此接口提供 API,用于使用标准 Maven 通道从 Mojo 向用户提供反馈。这里应该没有什么大的惊喜,尽管您可能会注意到方法 accept
java.lang.CharSequence
而不是
java.lang.String
. 提供这主要是为了方便,使开发人员能够将内容
StringBuffer
直接传递到记录器中,而不是首先通过调用
toString()
.
方法总结:
-
void debug( java.lang.CharSequence )
在调试 错误级别 向用户发送消息 。
-
void debug( java.lang.CharSequence, java.lang.Throwable )
在调试 错误级别向用户发送消息(以及伴随的异常) 。启用此错误级别时,将输出错误的堆栈跟踪。
-
void debug( java.lang.Throwable )
在调试 错误级别向用户发送异常 。启用此错误级别时,将输出此异常的堆栈跟踪。
-
void info( java.lang.CharSequence )
在信息 错误级别 向用户发送消息 。
-
void info( java.lang.CharSequence, java.lang.Throwable )
在信息 错误级别向用户发送消息(以及伴随的异常) 。启用此错误级别时,将输出错误的堆栈跟踪。
-
void info( java.lang.CharSequence )
在信息 错误级别向用户发送异常 。启用此错误级别时,将输出此异常的堆栈跟踪。
-
void warn( java.lang.CharSequence )
在警告 错误级别 向用户发送消息 。
-
void warn( java.lang.CharSequence, java.lang.Throwable )
在警告 错误级别向用户发送消息(以及伴随的异常) 。启用此错误级别时,将输出错误的堆栈跟踪。
-
void warn( java.lang.CharSequence )
在警告 错误级别向用户发送异常 。启用此错误级别时,将输出此异常的堆栈跟踪。
-
void error( java.lang.CharSequence )
在错误 错误级别 向用户发送消息 。
-
void error( java.lang.CharSequence, java.lang.Throwable )
在错误 错误级别向用户发送消息(以及伴随的异常) 。启用此错误级别时,将输出错误的堆栈跟踪。
-
void error( java.lang.CharSequence )
在错误 错误级别向用户发送异常 。启用此错误级别时,将输出此异常的堆栈跟踪。
描述符和注释
除了需要实现的接口和/或抽象基类方面的正常 Java 要求外,插件描述符必须伴随插件 jar 中的这些类。该描述符文件用于为一组 Mojo 提供有关参数和其他组件要求的元数据,以便 Maven 可以在执行 Mojo 之前初始化 Mojo 并验证其配置。因此,插件描述符具有每个 Mojo 规范有效所需的特定信息集,以及整个插件描述符本身的要求。
注意:在以下讨论中,粗体项目是描述符的元素名称以及支持该插件描述符的 Mojo Javadoc 标记(如果适用)。几个例子是: someElement (@annotation parameterName="parameterValue") 或 someOtherElement (@annotation <rawAnnotationValue>) 。
注意:从 maven-plugin-plugin 3.0 开始,现在可以使用 Maven Plugin Tools Java 5 Annotations等价于Mojo Javadoc tags。请参阅 使用注释文档。
插件描述符(请参阅描述符参考)必须在带有路径的 jar 资源中提供:
META-INF/maven/plugin.xml
,并且它必须包含以下内容:
描述符元素 | 必需的? | 笔记 |
---|---|---|
mojos |
是的 | 插件提供的每个 Mojo 的描述符,每个都包含在一个
mojo
子元素中。Mojo 描述符将在下面详细介绍。显然,没有任何声明 Mojos 的插件是没有意义的,因此
mojos
需要该元素以及至少一个
mojo
子元素。
|
dependencies |
是的 | 插件运行所需的一组依赖项。每个依赖项都在一个
dependency
子元素中提供。下面介绍了依赖项规范。由于所有插件都必须依赖于
maven-plugin-api
,因此实际上需要此元素。
使用插件工具集,可以从 POM 的依赖项中提取这些依赖项。
|
在插件描述符中指定的每个 Mojo 都必须提供以下内容(此处指定的注释在类级别):
描述符元素 | Mojo Javadoc 标记 | 必需的? | 笔记 | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
aggregator |
@aggregator |
不 | 标记此 Mojo 以以多模块方式运行它,即将构建与列为模块的项目集聚合。 | ||||||||||||||||||||||||||||||
configurator |
@configurator <roleHint> |
不 | 将参数值注入此 Mojo 时使用的配置器类型。该值通常从 Mojo 的实现语言推导出来,但可以指定为允许使用自定义 ComponentConfigurator 实现。注意:这只会在非常特殊的情况下使用,使用高度受控的可能值词汇表。(像这样的元素就是为什么使用描述符工具是个好主意的原因。) | ||||||||||||||||||||||||||||||
execute |
|
不 | 当这个目标被调用时,它会首先调用一个并行的生命周期,在给定的阶段结束。如果提供了目标而不是阶段,则该目标将单独执行。任何一个的执行都不会影响当前项目,而是
${executedProject} 在需要时使表达式可用。还可以提供备用生命周期:有关更多信息,请参阅
构建生命周期的文档。 |
||||||||||||||||||||||||||||||
executionStrategy |
@executionStrategy <strategy> |
不 | 指定执行策略。注意:自 Maven 3.0 起不受支持。 | ||||||||||||||||||||||||||||||
goal |
@goal <goalName> |
是的 | Mojo 的名称,用户将从命令行中引用以直接执行 Mojo,或在 POM 中引用以提供特定于 Mojo 的配置。 | ||||||||||||||||||||||||||||||
inheritByDefault |
@inheritByDefault <true|false> |
编号 默认值:true |
指定 Mojo 是继承的。注意:自 Maven 3.0 起不受支持。 | ||||||||||||||||||||||||||||||
instantiationStrategy |
@instantiationStrategy <per-lookup> |
编号 默认值:per-lookup |
指定实例化策略。 | ||||||||||||||||||||||||||||||
phase |
@phase <phaseName> |
不 |
如果用户未在 POM 中显式设置阶段,则定义将 mojo 执行绑定到的默认阶段。
注意:当插件声明添加到 POM 时,此注释不会自动运行 mojo。它仅使用户能够<phase> 从周围
元素中省略该<execution> 元素。
|
||||||||||||||||||||||||||||||
requiresDependencyResolution |
@requiresDependencyResolution <requiredClassPath> |
不 |
将此 Mojo 标记为需要在执行之前解析指定类路径中的依赖项。下面的矩阵说明了支持<requiredClassPath>(第一列)的哪些值以及它们将请求解析的依赖范围(第一行):
runtime . 如果注释根本不存在,则 mojo 不得对与 Maven 项目关联的工件做出任何假设。
|
||||||||||||||||||||||||||||||
requiresDependencyCollection |
@requiresDependencyCollection <requiredClassPath> |
不 |
将此 mojo 标记为需要有关构成指定类路径的依赖项的信息。顾名思义,这个注解类似于<requiredClassPath>@requiresDependencyResolution 并支持相同的值。重要的区别是这个注解不会解析依赖项的文件,即与 Maven 项目关联的工件可能缺少文件。因此,此注释适用于只想分析传递依赖项集的 mojo,特别是在早期生命周期阶段,由于尚未构建的项目,完全依赖项解析可能会失败。mojo 可以同时使用这个注解和@requiresDependencyResolution
同时。已收集但未请求解析的任何依赖项的解析状态是未定义的。从 Maven 3.0.
|
||||||||||||||||||||||||||||||
requiresDirectInvocation |
@requiresDirectInvocation <true|false> |
编号 默认值:false |
标记此 Mojo 以直接调用。注意:自 Maven 3.0 起不受支持。 | ||||||||||||||||||||||||||||||
requiresOnline |
@requiresOnline <true|false> |
编号 默认值:false |
将此 Mojo 标记为需要在线模式才能运行。 | ||||||||||||||||||||||||||||||
requiresProject |
@requiresProject <true|false> |
编号 默认值:true |
将此 Mojo 标记为在项目内部运行。 | ||||||||||||||||||||||||||||||
requiresReports |
@requiresReports <true|false> |
编号 默认值:false |
将此 Mojo 标记为需要报告。注意:自 Maven 3.0 起不受支持。 | ||||||||||||||||||||||||||||||
threadSafe |
@threadSafe <true|false> |
编号 默认值:false |
将此 mojo 标记为线程安全的,即 mojo 在并行构建期间安全地支持并发执行。在并行构建会话期间使用没有此注释的 Mojos 将使 Maven 输出警告。@threadSafe 没有标签值的速记符号等价于@threadSafe true . 从 Maven 3.0.
|
||||||||||||||||||||||||||||||
description |
无(检测到) | 不 | 此 Mojo 功能的描述。使用该工具集,这将是提供的类级别 Javadoc 描述。注意:虽然这不是 Mojo 规范的必需部分,但应该提供它以支持未来的工具对浏览等的支持,并且为了清晰起见。 | ||||||||||||||||||||||||||||||
implementation |
无(检测到) | 是的 | Mojo 的完全限定类名(或非 Java Mojos 的脚本路径)。 | ||||||||||||||||||||||||||||||
language |
无(检测到) | 编号 默认值:java |
此 Mojo 的实现语言(Java、beanshell 等)。 | ||||||||||||||||||||||||||||||
deprecated |
@deprecated <deprecated-text> |
不 | 指定 API 弃用 Mojo 时的版本。类似于已弃用的 Javadoc。当用户尝试配置标记为已弃用的参数时,这将触发警告。 | ||||||||||||||||||||||||||||||
since |
@since <since-text> |
不 | 指定将 Mojo 添加到 API 时的版本。此后类似于 Javadoc。 |
每个 Mojo 都指定了它期望工作的参数。这些参数是 Mojo 与外部世界的链接,将通过 POM/项目值、插件配置(来自 POM 和配置默认值)和系统属性的组合来满足。
注意[1]:对于这个关于 Mojo 参数的讨论,单个注释可以跨越描述符规范中该参数的多个元素。本节中重复的注解声明将用于分别详细说明注解的每个参数。
注意[2]:在许多情况下,只需使用 @parameter注释 Mojo 字段 就足以允许使用 POM 配置元素为该参数注入值。下面的讨论显示了此注释以及其他注释的高级用法。
Mojo 的每个参数都必须在插件描述符中指定,如下所示:
描述符元素 | Mojo Javadoc 标记 | 必需的? | 笔记 |
---|---|---|---|
alias |
@parameter alias="myAlias" |
不 | 指定可用于从 POM 配置此参数的别名。这主要用于提高用户友好性,其中 Mojo 字段名称对用户来说不直观,或者不利于通过 POM 进行配置。 |
configuration |
@component role="..." roleHint="..." |
不 | 使用 Plexus 组件的实例填充该字段。这就像
在 Plexus 组件中声明需求一样。默认要求将具有与声明的字段类型相同的角色,并将使用角色提示“默认”。您可以通过提供一个role 和/或roleHint 参数来自定义其中任何一个。
例如
@component role="org.apache.maven.artifact.ArtifactHandler"
roleHint="ear" 。注意:这与不推荐使用的参数形式相同:@parameter
expression="${component.yourpackage.YourComponentClass#roleHint}" 。 |
configuration |
行家插件插件 2.x:@parameter expression="${aSystemProperty}"
default-value="${anExpression}" 行家插件插件 3.x: @parameter property="aSystemProperty"
default-value="${anExpression}" |
不 |
指定用于计算要在构建时注入 Mojo 的此参数的值的表达式。 给出的表达式
注意:如果既不指定 |
editable |
@readonly |
不 | 指定此参数不能由用户直接配置(如 POM 指定配置的情况)。当您想要强制用户使用通用 POM 元素而不是插件配置时,这很有用,例如您想要使用工件的最终名称作为参数的情况。在这种情况下,您希望用户修改 <build><finalName/></build> 而不是直接在插件配置部分中指定 finalName 的值。确保 - 例如 - 需要 Artifact 类型的项目的 List 类型的参数不会得到一个满是字符串的 List 也是有用的。注意:此注释的规范将参数标记为不可编辑; |
required |
@required |
不 | Mojo 运行是否需要此参数。这用于在注入之前验证 Mojo 的配置,以及在从某个半状态执行 Mojo 之前。注意:此注释的规范根据需要标记参数;没有真/假值。 |
description |
无(检测到) | 不 | 该参数在 Mojo 中的使用说明。使用工具集,这被检测为该字段的 Javadoc 描述。注意:虽然这不是参数规范的必需部分,但应该提供它以启用未来工具对浏览等的支持,并且为了清晰起见。 |
name |
无(检测到) | 是的 | 参数的名称,用于从 Mojo 声明的默认值(下文讨论)或 POM 配置此参数。使用工具集,这被检测为 Java 字段名称。 |
type |
无(检测到) | 是的 | 此参数的 Java 类型。这用于验证用于计算应为该参数注入 Mojo 的值的任何表达式的结果。 使用工具集,将其检测为与该参数对应的 Java 字段的类。 |
deprecated |
@deprecated <deprecated-text> |
不 | 指定 API 弃用 Mojo 时的版本。类似于已弃用的 Javadoc。当用户尝试配置标记为已弃用的参数时,这将触发警告。 |
since |
@since <since-text> |
不 | 指定将 Mojo 添加到 API 时的版本。此后类似于 Javadoc。 |
插件描述符的最后一个组件是依赖项。这使插件能够独立于其 POM 运行(或至少声明它需要运行的库)。依赖项取自插件计算的依赖项的 运行时 范围(来自 POM)。依赖项的指定方式与 POM 中完全相同,除了 <scope> 元素(插件描述符中的所有依赖项都假定为运行时,因为这是插件的运行时配置文件)。
插件工具
到目前为止,我们已经多次提到插件工具,但没有告诉您它们是什么或如何使用它们。Maven 没有手动编写(和维护)上面详述的元数据,而是附带了一些工具来帮助完成这项任务。事实上,插件开发者唯一需要做的就是在 POM 中声明他的项目是一个插件。完成此操作后,Maven 将调用适当的描述符生成器等,以生成可以在 Maven 构建中使用的工件。如上所述,可以通过 Javadoc 注释(未来可能还有 JDK5 注释)注入可选元数据,从而实现 Mojo 和用户之间更丰富的交互。
项目描述符 (POM) 要求
从 POM 来看,Maven 插件项目看起来与任何其他项目都非常相似。对于纯 Java 插件,差异甚至比基于脚本的插件小。下面详细介绍了构建 Maven 插件工件所需的 POM 元素。
POM 元素 | Java Mojos 需要吗? | 样本声明 | 笔记 |
---|---|---|---|
包装 | 是的 |
<packaging>
maven-plugin
</packaging>
|
POM 必须声明一个包装元素,将这个项目描述为一个 Maven 插件项目。 |
脚本源目录 | 不 |
<scriptSourceDirectory>
src/main/scripts
</scriptSourceDirectory>
|
对于基于脚本的 Mojos(本文档中没有详细介绍),POM 必须包含一个附加元素,以区分脚本源和(可选)Java 支持类。这个元素是scriptSourceDirectory , 在build 节内。该目录包含在生成的工件中伴随任何已编译代码的资源列表中。它与构建部分中的资源分开指定,以表示其作为脚本的备用源目录的特殊状态。 |
进行上述更改后,开发人员可以简单地调用
mvn install
将插件安装到本地存储库。(任何其他标准生命周期目标,如 package、deploy 等也以类似的方式提供。)
IDE 集成
如果您使用 JetBrains IntelliJ IDEA 开发插件,则可以使用以下内容将 javadoc 注释配置为实时模板。
- 下载此文件,并将其放入
$USER_HOME/.IntelliJIdea/config/templates
- (重新)启动 IntelliJ IDEA(模板在启动时加载)
- 将以下列表添加到 Settings -> IDE -> Errors -> General -> Unknown javadoc tags -> Additional javadoc tags
- 聚合器、执行、目标、阶段、需要直接调用、需要项目、需要报告、需要在线、参数、组件、需要、只读
资源
本节仅提供一个指针列表以获取更多信息。