在本节中,我们将构建一个简单的插件,其中一个目标不带参数,只是在运行时在屏幕上显示一条消息。在此过程中,我们将介绍设置项目以创建插件的基础知识,定义目标代码的Java mojo的最小内容,以及执行mojo的几种方法。
最简单的是,Java mojo只包含一个代表一个插件目标的类。不需要像EJB这样的多个类,尽管包含许多类似mojos的插件可能会使用抽象超类来为mojos合并所有mojos共有的代码。
在处理源码树以查找mojos时,plugin-tools会查找带有@Mojo Java 5注释或goaljavadoc注释的类。具有此批注的任何类都包含在插件配置文件中。
下面列出的是一个没有参数的简单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." ); } }
所有Mojo注解都由Mojo API规范描述。
一旦为插件编写了mojos,就可以构建插件了。要正确执行此操作,项目的描述符需要正确设置许多设置:
groupId | 这是插件的组ID,应该与mojos使用的包的公共前缀匹配 |
artifactId | 这是插件的名称 |
version | 这是插件的版本 |
packaging | 这应该设置为maven-plugin |
dependencies | 必须声明Maven Plugin Tools 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> </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-pluginpackaging定义的标准构建生命周期中一些插件目标:
compile | 编译插件的Java代码 |
process-classes | 提取数据以构建插件描述符 |
test | 运行插件的单元测试 |
package | 构建插件jar |
install | 在本地存储库中安装插件jar |
deploy | 将插件jar部署到远程存储库 |
有关更多详细信息,你可以查看maven-plugin打包的详细绑定。
执行新插件的最直接方法是直接在命令行上指定插件goal。为此,你需要在项目中配置hello-maven-plugin插件:
... <build> <plugins> <plugin> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> </plugin> </plugins> </build> ...
而且,你需要以下列形式指定完全合格的goal:
mvn groupId:artifactId:version:goal
例如,要在示例插件中运行简单的mojo,你可以在命令行中输入mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi。
提示:运行独立goal不需要指定版本。
有几种方法可以减少命令所需的输入量:
最后,你还可以将插件的groupId添加到默认搜索的groupId列表中。为此,你需要将以下内容添加到${user.home}/.m2/settings.xml文件中:
<pluginGroups> <pluginGroup>sample.plugin</pluginGroup> </pluginGroups>
你还可以配置插件以将特定goal附加到构建生命周期的特定phase。这是一个例子:
<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绑定到生命周期中的阶段的更多信息,请参阅Build Lifecycle文档。
要创建新的插件项目,可以使用Mojoarchetype和以下命令行:
mvn archetype:generate \ -DgroupId=sample.plugin \ -DartifactId=hello-maven-plugin \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-plugin
没有参数,mojo不太可能非常有用。参数提供了一些非常重要的功能:
定义参数就像在mojo中创建实例变量并添加适当的注释一样简单。下面列出的是简单mojo的参数示例:
/** * The greeting to display. */ @Parameter(property = "sayhi.greeting", defaultValue = "Hello World!") private String greeting;
注释之前的部分是参数的描述。参数注解将变量标识为mojo参数,注解的defaultValue参数定义变量的默认值。该值可以包括引用项目的表达式,例如${project.version}(更多表达式可以在“参数表达式”文档中找到)。property参数可用于允许通过引用用户通过-D选项设置的系统属性从命令行配置mojo参数。
配置插件的参数值是在Maven项目中的pom.xml文件中完成的,作为在项目中定义插件的一部分。配置插件的示例:
<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。读取配置时,使用Integer.parseInt()或相应类的valueOf()方法将XML文件中的文本转换为整数值。这意味着字符串必须是有效的十进制整数值,仅包含数字0到9,前面带有可选项-则是负值。例:
/** * My Integer. */ @Parameter private Integer myInteger;
<myInteger>10</myInteger>
这包括变量类型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:55PM)。请注意,解析是使用DateFormat.parse()完成的,这允许在格式化方面有所宽容。如果该方法可以解析指定的日期和时间,即使它与上述模式不完全匹配,也可以。例:
/** * 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;
下面列出了各种类型的复合对象,它们可以用作mojos中的参数,以及有关如何解释POM中的值的任何规则。通常,为保存参数值而创建的对象的类(以及参数值中每个元素的类)的确定如下(产生有效类的第一步):
一旦定义了元素的类型,XML文件中的文本就会转换为适当类型的对象
通过多次指定参数来配置数组类型参数。例:
/** * My Array. */ @Parameter private String[] myArray;
<myArray> <param>value1</param> <param>value2</param> </myArray>
此类别包含实现java.util.Collection的任何类,例如ArrayList或HashSet。通过像数组一样多次指定参数来配置这些参数。例:
/** * My List. */ @Parameter private List myList;
<myList> <param>value1</param> <param>value2</param> </myList>
有关各个集合元素的映射的详细信息,请参阅映射列表。
此类别涵盖实现java.util.Map的任何类,例如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>的形式来配置这些参数。例:
/** * My Properties. */ @Parameter private Properties myProperties;
<myProperties> <property> <name>propertyName1</name> <value>propertyValue1</value> <property> <property> <name>propertyName2</name> <value>propertyValue2</value> <property> </myProperties>
你不限于使用私有字段映射,如果你试图让Mojos在Maven的上下文之外也可以被重复使用,那么这是很好的。对于上面的示例,我们可以使用下划线约定命名我们的私有字段,并提供可使用的setter配置映射机制。所以我们的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。