介绍
本指南旨在帮助用户为 Maven 开发 Java 插件。
重要通知:插件命名约定和 Apache Maven 商标
您通常会为您的插件命名<yourplugin>-maven-plugin
。
强烈建议不要调用它maven-<yourplugin>-plugin
(注意“Maven”在插件名称的开头),因为它是Apache Maven 团队使用 groupId维护的官方 Apache Maven 插件的保留命名模式。使用这种命名模式是对 Apache Maven 商标的侵犯。org.apache.maven.plugins
你的第一个插件
在本节中,我们将构建一个简单的插件,其目标是不带任何参数,并且在运行时仅在屏幕上显示一条消息。在此过程中,我们将介绍设置项目以创建插件的基础知识、定义目标代码的 Java mojo 的最小内容,以及执行 mojo 的几种方法。
你的第一个魔力
简而言之,Java mojo 仅由代表一个插件目标的单个类组成。不需要像 EJB 这样的多个类,尽管包含许多类似 mojo 的插件可能会使用 mojo 的抽象超类来整合所有 mojo 共有的代码。
在处理源代码树以查找 mojos 时,查找带有Java 5 注释或 " " javadoc 注释的类。任何带有此注解的类都包含在插件配置文件中。 plugin-tools
@Mojo
goal
一个简单的魔力
下面列出的是一个没有参数的简单 mojo 类。这与 mojo 一样简单。列出之后是对源的各个部分的描述。
package sample.plugin; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; /** * Says "Hi" to the user. * */ @Mojo( name = "sayhi") public class GreetingMojo extends AbstractMojo { public void execute() throws MojoExecutionException { getLog().info( "Hello, world." ); } }
- 除了方法之外,该类
org.apache.maven.plugin.AbstractMojo
提供了实现 mojo 所需的大部分基础设施execute
。 - 注释 "
@Mojo
" 是必需的,它控制着 mojo 的执行方式和时间。 - 该
execute
方法可以抛出两个异常:org.apache.maven.plugin.MojoExecutionException
如果出现意外问题。抛出此异常会导致显示“BUILD ERROR”消息。org.apache.maven.plugin.MojoFailureException
如果出现预期的问题(例如编译失败)。抛出此异常会导致显示“BUILD FAILURE”消息。
- 该
getLog
方法(定义在 中AbstractMojo
)返回一个类似 log4j 的记录器对象,它允许插件在“调试”、“信息”、“警告”和“错误”级别创建消息。此记录器是向用户显示信息的公认方式。请查看检索 Mojo Logger部分以获取有关其正确使用的提示。
Mojo API 规范描述了所有 Mojo 注释。
项目定义
一旦为插件编写了 mojo,就该构建插件了。要正确执行此操作,项目的描述符需要正确设置许多设置:
groupId |
这是插件的组 ID,应该与 mojos 使用的包的公共前缀匹配 |
artifactId |
这是插件的名称 |
version |
这是插件的版本 |
packaging |
这应该设置为“ maven-plugin ” |
dependencies |
必须向 Maven 插件工具 API 声明依赖项以解析“ AbstractMojo ”和相关类 |
下面列出的是示例 mojo 项目的 pom 的说明,其参数设置如上表所述:
<project> <modelVersion>4.0.0</modelVersion> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <name>Sample Parameter-less Maven Plugin</name> <dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>3.0</version> <scope>provided</scope> </dependency> <!-- dependencies to annotations --> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.4</version> <scope>provided</scope> </dependency> </dependencies> </project>
构建插件
maven-plugin
与打包定义的标准构建生命周期绑定的插件目标很少:
compile |
为插件编译 Java 代码 |
process-classes |
提取数据以构建插件描述符 |
test |
运行插件的单元测试 |
package |
构建插件 jar |
install |
在本地存储库中安装插件 jar |
deploy |
将插件 jar 部署到远程存储库 |
有关更多详细信息,您可以查看包装的详细绑定maven-plugin
。
执行你的第一个 Mojo
执行新插件最直接的方法是直接在命令行中指定插件目标。为此,您需要hello-maven-plugin
在项目中配置插件:
... <build> <plugins> <plugin> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> </plugin> </plugins> </build> ...
并且,您需要以以下形式指定完全限定的目标:
mvn groupId:artifactId:version:goal
例如,要运行示例插件中的简单 mojo,您可以mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi
在命令行中输入“”。
提示:version
运行独立目标不需要。
缩短命令行
有几种方法可以减少所需的输入量:
- 如果您需要运行安装在本地存储库中的插件的最新版本,则可以省略其版本号。所以只需使用“
mvn sample.plugin:hello-maven-plugin:sayhi
”来运行你的插件。 - 您可以为插件分配一个缩短的前缀,例如
mvn hello:sayhi
. 如果您遵循使用约定${prefix}-maven-plugin
(或者maven-${prefix}-plugin
如果插件是 Apache Maven 项目的一部分),这将自动完成。您也可以通过额外的配置来分配一个 - 更多信息请参见Plugin Prefix Mapping 简介。 - 最后,您还可以将插件的 groupId 添加到默认搜索的 groupId 列表中。为此,您需要将以下内容添加到您的
${user.home}/.m2/settings.xml
文件中:<pluginGroups> <pluginGroup>sample.plugin</pluginGroup> </pluginGroups>
此时,您可以使用 " mvn hello:sayhi
" 运行 mojo。
将 Mojo 附加到构建生命周期
您还可以配置插件以将特定目标附加到构建生命周期的特定阶段。这是一个例子:
<build> <plugins> <plugin> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <executions> <execution> <phase>compile</phase> <goals> <goal>sayhi</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
这会导致在编译 Java 代码时执行简单的 mojo。有关将 mojo 绑定到生命周期中的各个阶段的更多信息,请参阅构建生命周期文档。
Mojo 原型
要创建一个新的插件项目,您可以使用 Mojo原型和以下命令行:
mvn archetype:generate \ -DgroupId=sample.plugin \ -DartifactId=hello-maven-plugin \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-plugin
参数
如果没有参数,mojo 不太可能非常有用。参数提供了一些非常重要的功能:
- 它提供了钩子,允许用户调整插件的操作以满足他们的需要。
- 它提供了一种从 POM 中轻松提取元素值的方法,而无需导航对象。
在 Mojo 中定义参数
定义参数就像在 mojo 中创建实例变量并添加适当的注释一样简单。下面列出的是简单 mojo 的参数示例:
/** * The greeting to display. */ @Parameter( property = "sayhi.greeting", defaultValue = "Hello World!" ) private String greeting;
注释之前的部分是参数的描述。注释将parameter
变量标识为 mojo 参数。注释的defaultValue
参数定义了变量的默认值。该值可以包括引用项目的表达式,例如“ ${project.version}
”(更多可以在“参数表达式”文档中找到)。通过引用用户通过选项设置的系统属性,该property
参数可用于允许从命令行配置 mojo 参数。-D
在项目中配置参数
为插件配置参数值是在pom.xml
文件中的 Maven 项目中完成的,作为在项目中定义插件的一部分。配置插件的示例:
<plugin> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <configuration> <greeting>Welcome</greeting> </configuration> </plugin>
在配置部分,元素名称(“ greeting
”)是参数名称,元素的内容(“ Welcome
”)是要分配给参数的值。
注意:更多细节可以在配置插件指南中找到。
具有一个值的参数类型
下面列出了各种类型的简单变量,它们可以用作你的 mojos 中的参数,以及关于如何解释 POM 中的值的任何规则。
布尔值
这包括类型化的变量boolean
和Boolean
. 读取配置时,文本“ true
”导致参数设置为 true,所有其他文本导致参数设置为 false。例子:
/** * My boolean. */ @Parameter private boolean myBoolean;
<myBoolean>true</myBoolean>
整数
byte
这包括类型为 、Byte
、int
、Integer
、long
、Long
、short
和的变量Short
。读取配置时,XML 文件中的文本会使用相应类Integer.parseInt()
的方法或方法转换为整数值。valueOf()
这意味着字符串必须是有效的十进制整数值,仅由数字 0 到 9 组成-
,前面有一个可选的负值。例子:
/** * My Integer. */ @Parameter private Integer myInteger;
<myInteger>10</myInteger>
浮点数字
double
这包括类型为 、Double
、float
和的变量Float
。valueOf()
读取配置时,使用相应类的方法将 XML 文件中的文本转换为二进制形式。这意味着字符串可以采用 Java 语言规范第 3.10.2 节中指定的任何格式。一些有效值样本是1.0
和6.02E+23
。
/** * My Double. */ @Parameter private Double myDouble;
<myDouble>1.0</myDouble>
日期
这包括类型化的变量Date
。读取配置时,XML 文件中的文本使用以下日期格式之一进行转换:“ yyyy-MM-dd HH:mm:ss.S a
”(示例日期为“2005-10-06 2:22:55.1 PM”)或“ yyyy-MM-dd HH:mm:ssa
”(示例日期为“2005-10-06 下午 2:22:55”)。请注意,解析是使用DateFormat.parse()
which 允许格式化的一些宽大处理完成的。如果该方法可以解析指定的日期和时间,即使它与上面的模式不完全匹配,它也会这样做。例子:
/** * My Date. */ @Parameter private Date myDate;
<myDate>2005-10-06 2:22:55.1 PM</myDate>
文件和目录
这包括类型化的变量File
。读取配置时,XML 文件中的文本用作所需文件或目录的路径。如果路径是相对的(不以 开头/
或类似的驱动器C:
号),则路径相对于包含 POM 的目录。例子:
/** * My File. */ @Parameter private File myFile;
<myFile>c:\temp</myFile>
网址
这包括类型化的变量URL
。读取配置时,使用 XML 文件中的文本作为 URL。格式必须遵循 RFC 2396 指南,并且看起来像任何 Web 浏览器 URL ( scheme://host:port/path/to/file
)。在转换 URL 时,对 URL 的任何部分的内容都没有限制。
/** * My URL. */ @Parameter private URL myURL;
<myURL>http://maven.apache.org</myURL>
纯文本
char
这包括类型为 、Character
、StringBuffer
和的变量String
。读取配置时,将 XML 文件中的文本用作要分配给参数的值。对于char
和Character
参数,只使用文本的第一个字符。
枚举
也可以使用枚举类型参数。首先你需要定义你的枚举类型,然后你可以在参数定义中使用枚举类型:
public enum Color { GREEN, RED, BLUE } /** * My Enum */ @Parameter private Color myColor;
所以让我们看看你可以在你的 pom 配置中使用这样的枚举:
<myColor>GREEN</myColor>
您还可以将枚举类型中的元素用作 defaultValues,如下所示:
public enum Color { GREEN, RED, BLUE } /** * My Enum */ @Parameter(defaultValue = "GREEN") private Color myColor;
具有多个值的参数类型
下面列出了可以用作 mojo 中参数的各种类型的复合对象,以及有关如何解释 POM 中的值的任何规则。通常,为保存参数值而创建的对象的类(以及参数值中每个元素的类)确定如下(使用产生有效类的第一步):
- 如果 XML 元素包含
implementation
提示属性,则使用 - 如果 XML 标记包含 a
.
,请尝试将其作为完全限定的类名 - 尝试将 XML 标记(首字母大写)作为与正在配置的 mojo/object 相同的包中的类
- 对于数组,使用数组的组件类型(例如,
String
用于String[]
参数);对于集合和地图,使用在 mojo 配置中为集合或地图指定的类;用于String
集合中的条目和地图中的值
一旦定义了元素的类型,XML 文件中的文本就会被转换为适当的对象类型
数组
数组类型参数是通过多次指定参数来配置的。例子:
/** * My Array. */ @Parameter private String[] myArray;
<myArray> <param>value1</param> <param>value2</param> </myArray>
收藏品
此类别涵盖任何实现java.util.Collection
如ArrayList
or的类HashSet
。这些参数是通过多次指定参数来配置的,就像一个数组一样。例子:
/** * My List. */ @Parameter private List myList;
<myList> <param>value1</param> <param>value2</param> </myList>
有关各个集合元素映射的详细信息,请参阅映射列表。
地图
此类别涵盖任何实现但未实现的java.util.Map
类。这些参数是通过在参数配置的表单中包含 XML 标记来配置的。例子:HashMap
java.util.Properties
<key>value</key>
/** * My Map. */ @Parameter private Map myMap;
<myMap> <key1>value1</key1> <key2>value2</key2> </myMap>
特性
此类别涵盖了实现的任何地图java.util.Properties
。这些参数是通过 <property><name>myName</name> <value>myValue</value> </property>
在参数配置的表单中包含 XML 标记来配置的。例子:
/** * My Properties. */ @Parameter private Properties myProperties;
<myProperties> <property> <name>propertyName1</name> <value>propertyValue1</value> <property> <property> <name>propertyName2</name> <value>propertyValue2</value> <property> </myProperties>
其他项目类别
此类别涵盖任何不实现java.util.Map
、java.util.Collection
或的类java.util.Dictionary
。例子:
/** * My Object. */ @Parameter private MyObject myObject;
<myObject> <myField>test</myField> </myObject>
有关用于配置此类参数的策略的详细信息,请参阅映射复杂对象。
使用二传手
您不限于使用私有字段映射,如果您试图使您的 Mojos 在 Maven 上下文之外可重复使用,这很好。使用上面的示例,我们可以使用下划线约定命名我们的私有字段,并提供配置映射机制可以使用的设置器。所以我们的 Mojo 看起来像下面这样:
public class MyQueryMojo extends AbstractMojo { @Parameter(property="url") private String _url; @Parameter(property="timeout") private int _timeout; @Parameter(property="options") private String[] _options; public void setUrl( String url ) { _url = url; } public void setTimeout( int timeout ) { _timeout = timeout; } public void setOptions( String[] options ) { _options = options; } public void execute() throws MojoExecutionException { ... } }
请注意每个参数的属性名称规范,它告诉 Maven 当字段名称与插件配置中参数的预期名称不匹配时使用什么 setter 和 getter。
资源
- Mojo 文档:Mojo API、Mojo 注释
- Maven 插件测试工具:Mojos 的测试框架。
- Plexus:Maven 使用的 IoC 容器。
- Plexus Common Utilities:一组对 Mojo 开发有用的实用程序类。
- Commons IO:一组对文件/路径处理有用的实用程序类。
- 常见错误和陷阱:有问题的编码模式概述。