如何创建Maven插件

2023/05/24

1. 概述

Maven提供了各种各样的插件来帮助我们构建项目。但是,有时我们可能会发现这些插件不够我们使用,我们必须开发自己的插件。

幸运的是,Maven提供了一些有用的工具来帮助我们完成这个过程。

在本教程中,我们将逐步演示如何从头开始创建Maven插件。

我们还将展示如何在项目中使用它,以及如何为它创建文档。

2. 创建插件

在本文中,我们将开发一个名为counter-maven-plugin的插件,该插件用于计算项目包含的依赖项的数量。当我们为插件选择名称时,遵循Maven推荐的插件命名约定非常重要

接下来我们需要做的就是创建一个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>cn.tuyucheng.taketoday</groupId>
    <artifactId>counter-maven-plugin</artifactId>
    <packaging>maven-plugin</packaging>
    <version>1.0.0</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>

注意,我们将packaging设置为maven-plugin

在本例中,我们手动创建了该项目,但也可以使用maven-archetype-mojo来生成插件项目:

mvn archetype:generate 
  -DgroupId=cn.tuyucheng.taketoday
  -DartifactId=counter-maven-plugin 
  -Dversion=1.0.0
  -DarchetypeGroupId=org.apache.maven.archetypes 
  -DarchetypeArtifactId=maven-archetype-mojo

执行此操作时,我们应该更新依赖项的默认版本,以使用最新版本。

3. 创建Mojo

现在需要创造我们的第一个mojo了。Mojo是一个Java类,代表我们的插件将执行的目标,一个插件包含一个或多个mojo

我们的mojo将负责计算一个项目的依赖数量。

3.1 添加依赖

在创建mojo之前,我们需要向pom.xml添加一些依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>3.8.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.6.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-project</artifactId>
        <version>2.2.1</version>
    </dependency>
</dependencies>

maven-plugin-api依赖项是必需的,它包含创建mojo所需的类和接口maven-plugin-annotations依赖可以方便地在我们的类中使用注解。maven-project依赖允许我们访问包含插件的项目的相关信息。

3.2 创建Mojo类

mojo必须实现Mojo接口,在我们的例子中,我们继承AbstractMojo,因此我们只需要实现execute()方法:

@Mojo(name = "dependency-counter", defaultPhase = LifecyclePhase.COMPILE)
public class DependencyCounterMojo extends AbstractMojo {
    // ...
}

正如我们所见,dependency-counter是目标(goal)的名称。另一方面,默认情况下,我们将其附加到compile阶段,因此在使用此目标时,不必指定阶段。

要访问项目信息,我们必须添加一个MavenProject作为参数:

@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;

该对象将在创建上下文时由Maven注入。

至此,我们就可以实现execute()方法并统计项目的依赖数量:

public void execute() throws MojoExecutionException, MojoFailureException {
	List<Dependency> dependencies = project.getDependencies();
	long numDependencies = dependencies.stream().count();
	getLog().info("Number of dependencies: " + numDependencies);
}

getLog()方法提供对Maven日志的访问,AbstractMojo已经处理了它的生命周期。

3.3 添加参数

我们之前添加的参数是只读的,用户无法配置。而且,它是由Maven注入的,所以我们可以说它有点特别。

在本节中,我们将添加一个参数,用户可以在其中指定要计算的依赖项的范围。

因此,让我们在mojo中添加一个scope参数:

@Parameter(property = "scope")
String scope;

我们只设置了property属性,它允许我们通过命令行或pom属性设置此属性。对于其他属性,我们可以使用默认值。

现在,我们修改execute()方法以使用此参数,并在调用count时过滤依赖项:

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);
}

官方文档中解释了更高级的参数类型。

4. 测试插件

我们已经完成了插件的开发,接下来让我们测试一下它是否有效。

首先,我们必须在本地仓库中安装插件:

mvn clean install

在接下来的部分中,我们首先了解如何从命令行运行我们的插件,然后介绍如何在Maven项目中使用它。

4.1 执行我们的插件

我们可以通过指定插件的完全限定名,在命令行中运行插件的目标:

mvn groupId:artifactId:version:goal

在我们的例子中,命令如下:

mvn cn.tuyucheng.taketoday:counter-maven-plugin:1.0.0:dependency-counter

但是,如果我们遵循了本教程开头提到的插件命名约定,Maven将解析插件的前缀,这样我们可以缩短编写命令:

mvn counter:dependency-counter

请注意,这个命令使用的是最新版本的插件。此外,请记住,我们必须将groupId添加到setting.xml(在maven安装目录的conf文件夹下)中的pluginGroups标签中,maven也会搜索该group:

<pluginGroups>
    <pluginGroup>cn.tuyucheng.taketoday</pluginGroup>
</pluginGroups>

如果我们观察命令输出,我们可以看到插件统计了pom.xml中的依赖项数量。

我们还可以通过命令行属性设置scope参数:

mvn counter:dependency-counter -Dscope=test

请注意,scope名称是我们在mojo中参数的property属性中定义的名称。

4.2 在项目中使用我们的插件

现在我们创建一个非常简单的Maven项目来测试插件的使用,其中包含一些依赖,我们的插件将计算这些依赖项的数量:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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>cn.tuyucheng.taketoday</groupId>
    <artifactId>usage-example</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <version>${junit-jupiter.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <junit-jupiter.version>5.8.1</junit-jupiter.version>
    </properties>
</project>

最后一件事是将我们的插件添加到<build>中,我们必须明确设置我们想要运行dependency-counter目标:

<build>
    <plugins>
        <plugin>
            <groupId>cn.tuyucheng.taketoday</groupId>
            <artifactId>counter-maven-plugin</artifactId>
            <version>1.0.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>dependency-counter</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <scope>test</scope>
            </configuration>
        </plugin>
    </plugins>
</build>

请注意,我们已经在<configuration>标签中指定了scope参数。此外,我们没有指定任何阶段,因为默认情况下我们的mojo附加到编译阶段。

现在,我们只需要运行编译阶段来执行我们的插件:

mvn clean compile

我们的插件将打印测试范围依赖项的数量:

在本教程中,我们不会介绍如何为插件编写单元测试或集成测试,但Maven也提供了一些机制来实现这一点。

5. 添加文档

当我们创建一个Maven插件时,生成文档以便于其他人使用是很重要的

我们将要介绍如何使用maven-plugin-plugin生成此文档。

maven-plugin-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>

然后,我们必须确保已经将javadoc添加到我们的Mojo类中,并在插件的pom.xml中添加一些元数据

<organization>
    <name>Tuyucheng</name>
    <url>https://www.tuyucheng.com/</url>
</organization>

之后,我们需要在我们的pom.xml中添加一个<reporting>标签:

<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>

最后,我们将使用maven site命令生成文档:

mvn site

在target文件夹中,我们可以找到一个site目录,其中包含生成的所有HTML文件,plugin-info.html是包含插件文档的文件:

在浏览器打开该html文件,我们可以看到插件的详细信息:

可以在Maven插件文档指南中找到更多添加到我们文档中的选项。

6. 总结

在本文中,我们演示了如何创建Maven插件。首先我们实现了一个简单的插件,它帮助我们了解了一个典型的Maven插件项目结构。然后,我们介绍了Maven提供的帮助我们开发插件的一些工具。

我们保持简单以使事情更清楚,但与此同时,我们提供了一些有用的链接,其中包含有关如何创建更强大的插件的必要信息。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章