介绍
This guide is intended to assist users in developing Java plugins for Maven 2.0.
本指南旨在帮助用户在 Maven 2.0 开发 Java 插件。
Important Notice: Plugin Naming Convention and Apache Maven Trademark
You will typically name your plugin <yourplugin>-maven-plugin.
通常这样命名你的插件 <yourplugin>-maven-plugin.
Calling it maven-<yourplugin>-plugin (note "Maven" is at the beginning of the plugin name) is strongly discouraged since it's a reserved naming pattern for official Apache Maven plugins maintained by the Apache Maven team with groupId org.apache.maven.plugins. Using this naming pattern is an infringement of the Apache Maven Trademark.
命名为 maven-<yourplugin>-plugin (注意“Maven”是插件名称的开头)是强烈反对的,因为它是由Apache Maven团队与groupld org.apache.maven.plugins保持的官方的Apache Maven Plugin保留的命名模式。使用这个命名模式Apache Maven商标的侵权。
你的第一个插件
In this section we will build a simple plugin which takes no parameters and simply displays a message on the screen when run. Along the way, we will cover the basics of setting up a project to create a plugin, the minimal contents of a Java mojo, and a couple ways to execute the mojo.
在本节中,我们将在本节中,我们将构建一个简单的插件,它不带任何参数,只是在运行时在屏幕上显示一条消息。接下来,我们将讨论建立一个项目,创建一个插件,内容最少的Java mojo和如何执行。
你的第一个Mojo
At its simplest, a Java mojo consists simply of a single class. There is no requirement for multiple classes like EJBs, although a plugin which contains a number of similar mojos is likely to use an abstract superclass for the mojos to consolidate code common to all mojos.
简单来说,Java mojo只是个独立的类。尽管插件包含大量类似的mojos,可使用抽象的超类mojos来定义共用的mojos代码。
When processing the source tree to find mojos, plugin-tools looks for classes with either @Mojo Java 5 annotation or "goal" javadoc annotation. Any class with this annotation are included in the plugin configuration file.
通过源码树去找到mojos,插件工具查找类的方式有2种,”@Mojo” Java 5的注解或”@goal“ javadoc的注解,任何有这个注解的类都包含在插件配置文件中。
简单的Mojo
Listed below is a simple mojo class which has no parameters. This is about as simple as a mojo can be. After the listing is a description of the various parts of the source.
下面是一个无参的简单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." ); } }
-
The class org.apache.maven.plugin.AbstractMojo provides most of the infrastructure required to implement a mojo except for the execute method.
类org.apache.maven.plugin.AbstractMojo提供了实现mojo的基础能力,除了execute方法,这个方法是你来实现的。 -
The annotation "@Mojo" is required and control how and when the mojo is executed.
注解@Mojo是控制mojo执行的方式和时间。 -
The execute method can throw two exceptions:
execute方法有2个异常-
org.apache.maven.plugin.MojoExecutionException if an unexpected problem occurs. Throwing this exception causes a "BUILD ERROR" message to be displayed.
如果发生错误是org.apache.maven.plugin.MojoExecutionException,引发此异常后会显示“BUILD ERROR”信息。 -
org.apache.maven.plugin.MojoFailureException if an expected problem (such as a compilation failure) occurs. Throwing this exception causes a "BUILD FAILURE" message to be displayed.
如果错误是org.apache.maven.plugin.MojoFailureException(例如编译失败),会抛出”BUILD FAILURE”信息。
-
org.apache.maven.plugin.MojoExecutionException if an unexpected problem occurs. Throwing this exception causes a "BUILD ERROR" message to be displayed.
-
The getLog method (defined in AbstractMojo) returns a log4j-like logger object which allows plugins to create messages at levels of "debug", "info", "warn", and "error". This logger is the accepted means to display information to the user. Please have a look at the section Retrieving the Mojo Logger for a hint on its proper usage.
getLog方法(AbstractMojo中定义)返回一个类似log4j的记录器对象,它允许在"debug", "info", "warn", 和 "error”级别来创建消息。这个记录器是通过公用的方法去显示信息给用户,
All Mojo annotations are described by the Mojo API Specification.
所有的Mojo注解的描述,点击Mojo API说明查看。
项目定义 Project Definition
Once the mojos have been written for the plugin, it is time to build the plugin. To do this properly, the project's descriptor needs to have a number of settings set properly:
groupId | This is the group ID for the plugin, and should match the common prefix to the packages used by the mojos |
artifactId | This is the name of the plugin |
version | This is the version of the plugin |
packaging | This should be set to "maven-plugin" |
dependencies | A dependency must be declared to the Maven Plugin Tools API to resolve "AbstractMojo" and related classes |
Listed below is an illustration of the sample mojo project's pom with the parameters set as described in the above table:
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>
生成Goals
There are few goals which are defined with the maven-plugin packaging as part of a standard build lifecycle:
Maven插件的打包,几个标准构建的生命周期:
compile | Compiles the Java code for the plugin and builds the plugin descriptor |
test | Runs the plugin's unit tests |
package | Builds the plugin jar |
install | Installs the plugin jar in the local repository |
deploy | Deploys the plugin jar to the remote repository |
执行你的第一个mojo
The most direct means of executing your new plugin is to specify the plugin goal directly on the command line. To do this, you need to configure the hello-maven-plugin plugin in you project:执行你的新插件最直接的方式是直接在命令行上指定插件的goal,要做到这一点,你需要在你的项目里引用hello-maven-plugin插件。
<build> <plugins> <plugin> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> </plugin> </plugins> </build>And, you need to specify a fully-qualified goal in the form of:
而且,你需要指定可用的goal,格式如下:
mvn groupId:artifactId:version:goalFor example, to run the simple mojo in the sample plugin, you would enter "mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi" on the command line.
例如刚才我们上面的例子,你可以在命令行上运行 ”mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi“来执行。
Tips: version is not required to run a standalone goal.
提示:运行一个单独的goal,version不是必须的。
缩短命令行
There are several ways to reduce the amount of required typing:
有几种方法来减少输入命令行的长度。
-
If you need to run the latest version of a plugin installed in your local repository, you can omit its version number. So just use "mvn sample.plugin:hello-maven-plugin:sayhi" to run your plugin.
如果你需要在本地库运行最新的版本插件,可以省略版本号,只需要"mvn sample.plugin:hello-maven-plugin:sayhi"就可以了。 -
You can assign a shortened prefix to your plugin, such as mvn hello:sayhi. This is done automatically if you follow the convention of using ${prefix}-maven-plugin (or maven-${prefix}-plugin if the plugin is part of the Apache Maven project). You may also assign one through additional configuration - for more information see Introduction to Plugin Prefix Mapping.
你可以给你的插件设置一个短的前缀,如”mvn hello:sayhi“,后面不翻译了,太啰嗦了。意思大概是命名规范要按照上面讲的,更多插件前缀信息,点击查看。 -
Finally, you can also add your plugin's groupId to the list of groupIds searched by default. To do this, you need to add the following to your ${user.home}/.m2/settings.xml file:
最后,你还可以把你插件的groupId添加到默认groupId组列表里,要做到这一点,你需要下面的配置信息添加到你的${user.home}/.m2/settings.xml文件里。
<pluginGroups> <pluginGroup>sample.plugin</pluginGroup> </pluginGroups>
At this point, you can run the mojo with "mvn hello:sayhi".
这样,你就可以用"mvn hello:sayhi"来运行了。
把mojo加到mvn构建的生命周期中
You can also configure your plugin to attach specific goals to a particular phase of the build lifecycle. Here is an example:你还可以配置指定的goals在mvn构建的特定阶段,下面是例子:
<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>
This causes the simple mojo to be executed whenever Java code is compiled. For more information on binding a mojo to phases in the lifecycle, please refer to the Build Lifecycle document.
每当Java代码执行compile就会调用mojo。点击查看更多结合不同的mvn生命周期的信息。
Mojo archetype
To create a new plugin project, you could using the Mojo archetype with the following command line:通过命令行,使用Mojo archetype创建一个插件项目。
mvn archetype:generate \ -DgroupId=sample.plugin \ -DartifactId=hello-maven-plugin \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-plugin
参数
It is unlikely that a mojo will be very useful without parameters. Parameters provide a few very important functions:参数提供一些非常重要的功能:
- It provides hooks to allow the user to adjust the operation of the plugin to suit their needs.
- 允许根据自己的需要调整插件。
- It provides a means to easily extract the value of elements from the POM without the need to navigate the objects.
- 方便的提取POM元素的值。
定义Mojo中的参数
Defining a parameter is as simple as creating an instance variable in the mojo and adding the proper annotations. Listed below is an example of a parameter for the simple mojo:定义参数很简单,看下面的例子。
/** * The greeting to display. */ @Parameter( property = "sayhi.greeting", defaultValue = "Hello World!" ) private String greeting;
The portion before the annotations is the description of the parameter. The parameter annotation identifies the variable as a mojo parameter. The defaultValue parameter of the annotation defines the default value for the variable. This value can include expressions which reference the project, such as "${project.version}" (more can be found in the "Parameter Expressions" document). The property parameter can be used to allow configuration of the mojo parameter from the command line by referencing a system property that the user sets via the -D option.
注解之前的部分是参数的描述,注解标识这个变量作为mojo的参数。注解的默认参数值定义为变量的默认值,该值可包含引用该项目的表达式,如”${project.version}”(更多可以在“参数表达式”文档中找到)。该属性参数允许通过命令行来引用配置系统属性,通过-D。
项目中的参数配置
Configuring the parameter values for a plugin is done in a Maven 2 project within the pom.xml file as part of defining the plugin in the project. An example of configuring a plugin:在pom文件中配置参数,实现参数的引用,配置例子如下:
<plugin> <groupId>sample.plugin</groupId> <artifactId>hello-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <configuration> <greeting>Welcome</greeting> </configuration> </plugin>In the configuration section, the element name ("greeting") is the parameter name and the contents of the element ("Welcome") is the value to be assigned to the parameter.
配置部分里,元素(“greeting”)是参数名,元素的内容的值是(“Welcome”)。
Note: More details can be found in the Guide to Configuring Plugins.
注意:点击查看更多配置插件细节。
Listed below are the various types of simple variables which can be used as parameters in your mojos, along with any rules on how the values in the POM are interpreted.
下面是不同类型的参数变量的例子。
Boolean
This includes variables typed boolean and Boolean. When reading the configuration, the text "true" causes the parameter to be set to true and all other text causes the parameter to be set to false. Example:
/** * My boolean. */ @Parameter private boolean myBoolean;
<myBoolean>true</myBoolean>
Fixed-Point Numbers
This includes variables typed byte, Byte, int, Integer, long, Long, short, and Short. When reading the configuration, the text in the XML file is converted to an integer value using either Integer.parseInt() or the valueOf() method of the appropriate class. This means that the strings must be valid decimal integer values, consisting only of the digits 0 to 9 with an optional - in front for a negative value. Example:
/** * My Integer. */ @Parameter private Integer myInteger;
<myInteger>10</myInteger>
Floating-Point Numbers
This includes variables typed double, Double, float, and Float. When reading the configuration, the text in the XML file is converted to binary form using the valueOf() method for the appropriate class. This means that the strings can take on any format specified in section 3.10.2 of the Java Language Specification. Some samples of valid values are 1.0 and 6.02E+23.
/** * My Double. */ @Parameter private Double myDouble;
<myDouble>1.0</myDouble>
Dates
This includes variables typed Date. When reading the configuration, the text in the XML file is converted using one of the following date formats: "yyyy-MM-dd HH:mm:ss.S a" (a sample date is "2005-10-06 2:22:55.1 PM") or "yyyy-MM-dd HH:mm:ssa" (a sample date is "2005-10-06 2:22:55PM"). Note that parsing is done using DateFormat.parse() which allows some leniency in formatting. If the method can parse a date and time out of what is specified it will do so even if it doesn't exactly match the patterns above. Example:
/** * My Date. */ @Parameter private Date myDate;
<myDate>2005-10-06 2:22:55.1 PM</myDate>
Files and Directories
This includes variables typed File. When reading the configuration, the text in the XML file is used as the path to the desired file or directory. If the path is relative (does not start with / or a drive letter like C:), the path is relative to the directory containing the POM. Example:
/** * My File. */ @Parameter private File myFile;
<myFile>c:\temp</myFile>
URLs
This includes variables typed URL. When reading the configuration, the text in the XML file is used as the URL. The format must follow the RFC 2396 guidelines, and looks like any web browser URL (scheme://host:port/path/to/file). No restrictions are placed on the content of any of the parts of the URL while converting the URL.
/** * My URL. */ @Parameter private URL myURL;
<myURL>https://maven.apache.org</myURL>
Plain Text
This includes variables typed char, Character, StringBuffer, and String. When reading the configuration, the text in the XML file is used as the value to be assigned to the parameter. For char and Character parameters, only the first character of the text is used.
Enums
Enumeration type parameters can also be used. First you need to define your enumeration type and afterwards you can use the enumeration type in the parameter definition:
public enum Color { GREEN, RED, BLUE } /** * My Enum */ @Parameter private Color myColor;
<myColor>GREEN</myColor>You can also use elements from the enumeration type as defaultValues like the following:
public enum Color { GREEN, RED, BLUE } /** * My Enum */ @Parameter(defaultValue = "GREEN") private Color myColor;
Parameter Types With Multiple Values
Listed below are the various types of composite objects which can be used as parameters in your mojos, along with any rules on how the values in the POM are interpreted. In general, the class of the object created to hold the parameter value (as well as the class for each element within the parameter value) is determined as follows (the first step which yields a valid class is used):
- If the XML element contains an implementation hint attribute, that is used
- If the XML tag contains a ., try that as a fully qualified class name
- Try the XML tag (with capitalized first letter) as a class in the same package as the mojo/object being configured
- For arrays, use the component type of the array (for example, use String for a String[] parameter); for collections and maps, use the class specified in the mojo configuration for the collection or map; use String for entries in a collection and values in a map
Once the type for the element is defined, the text in the XML file is converted to the appropriate type of object
Arrays
Array type parameters are configured by specifying the parameter multiple times. Example:
/** * My Array. */ @Parameter private String[] myArray;
<myArray> <param>value1</param> <param>value2</param> </myArray>
Collections
This category covers any class which implements java.util.Collection such as ArrayList or HashSet. These parameters are configured by specifying the parameter multiple times just like an array. Example:
/** * My List. */ @Parameter private List myList;
<myList> <param>value1</param> <param>value2</param> </myList>
For details on the mapping of the individual collection elements, see Mapping Lists.
Maps
This category covers any class which implements java.util.Map such as HashMap but does not implement java.util.Properties. These parameters are configured by including XML tags in the form <key>value</key> in the parameter configuration. Example:
/** * My Map. */ @Parameter private Map myMap;
<myMap> <key1>value1</key1> <key2>value2</key2> </myMap>
Properties
This category covers any map which implements java.util.Properties. These parameters are configured by including XML tags in the form <property><name>myName</name> <value>myValue</value> </property> in the parameter configuration. Example:
/** * My Properties. */ @Parameter private Properties myProperties;
<myProperties> <property> <name>propertyName1</name> <value>propertyValue1</value> <property> <property> <name>propertyName2</name> <value>propertyValue2</value> <property> </myProperties>
Other Object Classes
This category covers any class which does not implement java.util.Map, java.util.Collection, or java.util.Dictionary. Example:
/** * My Object. */ @Parameter private MyObject myObject;
<myObject> <myField>test</myField> </myObject>Please see Mapping Complex Objects for details on the strategy used to configure those kind of parameters.
Using Setters
You are not restricted to using private field mapping which is good if you are trying to make you Mojos resuable outside the context of Maven. Using the example above we could name our private fields using the underscore convention and provide setters that the configuration mapping mechanism can use. So our Mojo would look like the following:
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 { ... }Note the specification of the property name for each parameter which tells Maven what setter and getter to use when the field's name does not match the intended name of the parameter in the plugin configuration.
资源
- Mojo文档: Mojo API, Mojo注解
- Maven插件测试工具: 对你Mojos的测试架构.
- Plexus: 使用 Maven 的 IoC 容器.
- Plexus常见实用工具: Mojo开发实用工具类集.
- Commons IO:一整套file/path处理的实用工具类。.
- 常见的Bug和误区: 总结编码模式的问题.