1. Introduction
1.介绍
Maven offers a great variety of plugins to help us with the build of our project. However, we may find cases where these plugins are not enough and we have to develop our own.
Maven提供了大量的插件来帮助我们完成项目的构建。但是,我们可能会发现,这些插件不够用,我们必须自己开发。
Luckily, Maven provides some useful tools to help us in this process.
幸运的是,Maven提供了一些有用的工具来帮助我们完成这一过程。
In this tutorial, we’ll be quite practical and will show step-by-step how to create a Maven plugin from scratch.
在本教程中,我们将相当实用,逐步展示如何从头开始创建一个Maven插件。
We’ll also show how to use it in our projects and how to create documentation for it.
我们还将展示如何在我们的项目中使用它以及如何为它创建文档。
2. Creating a Plugin
2.创建一个插件
During this tutorial, we’ll develop a plugin called counter-maven-plugin that will count the number of dependencies that a project contains. It’s very important to follow the plugin naming convention that Maven recommends when we choose the name for our plugin.
在本教程中,我们将开发一个名为counter-maven-plugin的插件,用来计算项目中的依赖数量。在为我们的插件选择名称时,遵循Maven推荐的插件命名惯例非常重要。
Now that we know what we’re going to develop, the next thing we need to do is to create a Maven project. In the pom.xml we’ll define the groupId, artifactId and version of our plugin:
现在我们知道要开发什么了,接下来我们要做的是创建一个Maven项目。在pom.xml中,我们将定义插件的groupId、artifactId和version。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>counter-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>counter-maven-plugin Maven Mojo</name>
<url>http://maven.apache.org</url>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
</project>
Notice that we set the packaging to maven-plugin.
注意,我们将包装设置为maven-plugin。。
In this case, we’ve created the project manually but we could also do it by using the maven-archetype-mojo:
在本例中,我们手动创建了该项目,但我们也可以通过使用maven-archetype-mojo来实现。
mvn archetype:generate
-DgroupId=com.baeldung
-DartifactId=counter-maven-plugin
-Dversion=0.0.1-SNAPSHOT
-DarchetypeGroupId=org.apache.maven.archetypes
-DarchetypeArtifactId=maven-archetype-mojo
When doing this, we should update the default versions of the dependencies to use the latest ones.
在这样做的时候,我们应该更新依赖的默认版本,使用最新的版本。
3. Creating a Mojo
3.创造一种魔力
Now it’s time to create our first mojo. Mojo is a Java class that represents a goal that our plugin will execute. A plugin contains one or more mojos.
现在是时候创建我们的第一个mojo了。Mojo是一个Java类,代表我们的插件将执行的目标。一个插件包含一个或多个mojo。
Our mojo will be responsible for counting the number of dependencies of a project.
我们的mojo将负责计算一个项目的依赖性数量。
3.1. Adding Dependencies
3.1.添加依赖关系
Before creating the mojo, we need to add some dependencies to our pom.xml:
在创建mojo之前,我们需要向我们的pom.xml添加一些依赖项。
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
The maven-plugin-api dependency is required and contains the necessary classes and interfaces to create our mojo. The maven-plugin-annotations dependency comes in handy to use annotations in our classes. The maven-project dependency lets us access the information about the project where we’re including the plugin.
maven-plugin-api依赖项是必需的,它包含创建我们的mojo所需的类和接口。maven-plugin-annotations依赖关系对我们在类中使用注释很有帮助。maven-project依赖项让我们能够访问包括该插件在内的项目信息。
3.2. Creating the Mojo Class
3.2.创建Mojo类
Now we’re ready to create our mojo!
现在我们已经准备好创造我们的魔力了!
A mojo has to implement the Mojo interface. In our case, we’ll extend from AbstractMojo so we’ll only have to implement the execute method:
一个mojo必须实现Mojo接口。在我们的例子中,我们将从AbstractMojo扩展,所以我们只需要实现execute方法。
@Mojo(name = "dependency-counter", defaultPhase = LifecyclePhase.COMPILE)
public class DependencyCounterMojo extends AbstractMojo {
// ...
}
As we can see, dependency-counter is the name of the goal. On the other hand, we’ve attached it to the compile phase by default so we won’t necessarily have to specify a phase when using this goal.
我们可以看到,dependency-counter是这个目标的名字。另一方面,我们默认将其附加到compile阶段,所以我们在使用这个目标时不一定要指定一个阶段。
To have access to the project information, we have to add a MavenProject as a parameter:
为了获取项目信息,我们必须添加一个MavenProject作为参数。
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;
This object will be injected by Maven when the context is created.
Maven在创建上下文时将注入该对象。
At this point, we’re able to implement the execute method and count the number of dependencies of the project:
在这一点上,我们能够实现执行方法并计算项目的依赖数量。
public void execute() throws MojoExecutionException, MojoFailureException {
List<Dependency> dependencies = project.getDependencies();
long numDependencies = dependencies.stream().count();
getLog().info("Number of dependencies: " + numDependencies);
}
The getLog() method provides access to the Maven log. The AbstractMojo already handles its lifecycle.
getLog()方法提供了对Maven日志的访问。AbstractMojo已经处理了其生命周期。
3.3. Adding Parameters
3.3.添加参数
The parameter we’ve added before is read-only and can’t be configured by the user. Also, it’s injected by Maven so we could say it’s kind of special.
我们之前添加的参数是只读的,不能由用户配置。另外,它是由Maven注入的,所以我们可以说它有点特别。
In this section, we’re going to add a parameter where users can specify the scope of the dependencies that we want to count.
在这一节中,我们将添加一个参数,用户可以指定我们想要计算的依赖关系的范围。
Hence, let’s create a scope parameter in our mojo:
因此,让我们在我们的mojo中创建一个scope参数。
@Parameter(property = "scope")
String scope;
We’ve only set the property attribute. It allows us to set this property via the command line or a pom property. For the rest of the attributes, we’re fine with the default values.
我们只设置了propertyattribute。它允许我们通过命令行或pom属性来设置这个属性。对于其他的属性,我们用默认值就可以了。
Now we’ll modify our execute method to use this parameter and filter the dependencies when counting:
现在我们将修改我们的execute方法,以使用这个参数,并在计数时过滤依赖性。
public void execute() throws MojoExecutionException, MojoFailureException {
List<Dependency> dependencies = project.getDependencies();
long numDependencies = dependencies.stream()
.filter(d -> (scope == null || scope.isEmpty()) || scope.equals(d.getScope()))
.count();
getLog().info("Number of dependencies: " + numDependencies);
}
More advanced types of parameters are explained in the official documentation.
更高级的参数类型在官方文档中解释。
4. Testing the Plugin
4.测试插件
We’re done with the development of the plugin. Let’s test it to see if it works!
我们已经完成了该插件的开发工作。让我们测试一下,看看它是否有效
First of all, we have to install the plugin in our local repository:
首先,我们必须在我们的本地仓库中安装该插件。
mvn clean install
In the next sections, we’ll first see how to run our plugin from the command line. Then, we’ll also cover how to use it in a Maven project.
在接下来的章节中,我们将首先了解如何从命令行中运行我们的插件。然后,我们还将介绍如何在Maven项目中使用它。
4.1. Executing Our Plugin
4.1.执行我们的插件
We can run the goal of a plugin in the command line by specifying its fully qualified name:
我们可以在命令行中运行一个插件的目标,指定其完全合格的名称。
mvn groupId:artifactId:version:goal
In our case, it looks like this:
在我们的案例中,它看起来像这样。
mvn com.baeldung:counter-maven-plugin:0.0.1-SNAPSHOT:dependency-counter
However, if we’ve followed the plugin naming convention that we mentioned at the beginning of this tutorial, Maven will resolve the prefix of our plugin and we can shorten the command:
不过,如果我们遵循了本教程开头提到的插件命名惯例,Maven会解析我们的插件的前缀,我们可以缩短命令。
mvn counter:dependency-counter
Notice that this command is using the latest version of the plugin. Also, keep in mind that we have to add our groupId to the pluginGroups of our settings.xml so Maven also searches in this group:
请注意,这个命令使用的是最新版本的插件。另外,请记住,我们必须把我们的groupId添加到settings.xml的pluginGroups中,这样Maven也会在这个组中搜索。
<pluginGroups>
<pluginGroup>com.baeldung</pluginGroup>
</pluginGroups>
If we check the output of the command, we can see that the plugin counted the number of dependencies in the pom.xml of our plugin:
如果我们检查命令的输出,我们可以看到,该插件计算了我们插件的pom.xml中的依赖数量。
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.baeldung:counter-maven-plugin >------------------
[INFO] Building counter-maven-plugin Maven Mojo 0.0.1-SNAPSHOT
[INFO] ----------------------------[ maven-plugin ]----------------------------
[INFO]
[INFO] --- counter-maven-plugin:0.0.1-SNAPSHOT:dependency-counter (default-cli) @ counter-maven-plugin ---
[INFO] Number of dependencies: 3
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.529 s
[INFO] Finished at: 2019-11-30T20:43:41+01:00
[INFO] ------------------------------------------------------------------------
We can also set the scope parameter via command line properties:
我们还可以通过命令行属性设置scope参数。
mvn counter:dependency-counter -Dscope=test
Notice that the scope name is the one that we defined in the property attribute of our parameter in the mojo.
注意,scope的名字是我们在mojo中的参数的property属性中定义的。
4.2. Using Our Plugin in a Project
4.2.在一个项目中使用我们的插件
Let’s test now our plugin by using it in a project!
现在让我们通过在一个项目中使用它来测试我们的插件!
We’re going to create a very simple Maven project with some dependencies that our plugin will count:
我们将创建一个非常简单的Maven项目,其中有一些我们的插件要依赖的东西。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>example</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The last thing is to add our plugin to the build. We have to explicitly set that we want to run the dependency-counter goal:
最后一件事是将我们的插件添加到构建中。我们必须明确设置我们要运行dependency-counter目标。
<build>
<plugins>
<plugin>
<groupId>com.baeldung</groupId>
<artifactId>counter-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>dependency-counter</goal>
</goals>
</execution>
</executions>
<configuration>
<scope>test</scope>
</configuration>
</plugin>
</plugins>
</build>
Notice that we’ve specified the scope parameter in the configuration node. Also, we haven’t specified any phase because our mojo is attached to the compile phase by default.
注意到我们在configuration节点中指定了scope参数。另外,我们没有指定任何阶段,因为我们的mojo默认是连接到compile阶段的。
Now, we just need to run the compile phase to execute our plugin:
现在,我们只需要运行编译阶段来执行我们的插件。
mvn clean compile
And our plugin will print the number of test dependencies:
而我们的插件将打印test依赖的数量。
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< com.baeldung:example >------------------------
[INFO] Building example 0.0.1-SNAPSHOT
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ example ---
[INFO]
[INFO] --- counter-maven-plugin:0.0.1-SNAPSHOT:dependency-counter (default) @ example ---
[INFO] Number of dependencies: 1
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.627 s
[INFO] Finished at: 2019-11-25T18:57:22+01:00
[INFO] ------------------------------------------------------------------------
In this tutorial, we’re not covering how to write unit or integration tests for our plugin but Maven provides some mechanisms to do it.
在本教程中,我们不涉及如何为我们的插件编写单元或集成测试,但Maven提供了一些机制来做到这一点。
5. Adding Documentation
5.添加文档
When we create a Maven plugin, it’s important to generate documentation to make it easy for other people to use it.
当我们创建一个Maven插件时,生成文档以方便其他人使用是很重要的。
We’ll briefly cover how to generate this documentation with maven-plugin-plugin.
我们将简要介绍如何用maven-plugin-plugin来生成这种文档。
maven-plugin-plugin is already included in the project, but we’re gonna update it to use the latest version.
maven-plugin-plugin已经包含在项目中,但我们要更新它,使用最新版本。
Also, we’ll do the same for maven-site-plugin:
另外,我们对maven-site-plugin也要这样做。
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
Then, we have to make sure that we’ve added javadoc to our Mojo and also add some metadata in the pom.xml of the plugin:
然后,我们必须确保我们已经将javadoc添加到我们的Mojo中,并在插件的pom.xml中添加一些元数据。
<organization>
<name>Baeldung</name>
<url>https://www.baeldung.com/</url>
</organization>
After that, we need to add a reporting section in our pom.xml:
之后,我们需要在pom.xml中添加一个报告部分。
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
Finally, we’ll generate the documentation with the maven site command:
最后,我们将用maven site命令生成文档。
mvn site
Inside the target folder, we can find a site directory with all the HTML files generated. The plugin-info.html is the one containing the plugin documentation:
在目标文件夹中,我们可以找到一个site目录,里面有所有生成的HTML文件。plugin-info.html是包含插件文档的目录。
More options to add to our documentation can be found on the Maven plugin documentation guide.
可以在Maven插件文档指南上找到更多添加到我们文档中的选项。
6. Conclusion
6.结论
In this tutorial, we’ve shown how to create a Maven plugin. We first implemented a simple plugin, which helped us see a typical Maven plugin project structure. Then, we covered some of the tools that Maven provides to help us develop plugins.
在本教程中,我们展示了如何创建一个Maven插件。我们首先实现了一个简单的插件,这有助于我们看到一个典型的Maven插件项目结构。然后,我们介绍了Maven为帮助我们开发插件而提供的一些工具。
We’ve kept it simple to make things clearer, but at the same time, we’ve provided some useful links with the necessary information on how to create a more powerful plugin.
我们保持简单,使事情更清晰,但同时,我们也提供了一些有用的链接,其中有关于如何创建一个更强大的插件的必要信息。
As always, the full source code for the examples is available over on GitHub.
一如既往,这些示例的完整源代码可在GitHub上获取。