1. 简介

Maven 提供了丰富的插件生态来辅助项目构建。但实际开发中,标准插件未必能满足所有需求,这时候就需要自研定制插件。

好在 Maven 提供了一套成熟的插件开发工具链,让整个过程变得简单直接。

本文将手把手带你从零实现一个 Maven 插件,涵盖开发、测试、集成和文档生成全流程。目标不是讲理论,而是直接上干货,踩坑预警,确保你能快速上手

2. 创建插件项目

我们这次要实现的插件叫 counter-maven-plugin,功能是统计项目依赖数量。⚠️ 插件命名请严格遵守 Maven 官方规范<功能名>-maven-plugin,避免后续解析问题。

首先创建一个标准 Maven 项目,关键在于 pom.xml 的配置:

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

✅ 核心要点:

  • packaging 必须设为 maven-plugin
  • 使用 Java 8 编译(兼容性考虑)

你也可以用官方 Archetype 快速生成骨架:

mvn archetype:generate \
  -DgroupId=com.baeldung \
  -DartifactId=counter-maven-plugin \
  -Dversion=0.0.1-SNAPSHOT \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DarchetypeArtifactId=maven-archetype-mojo

生成后建议手动升级依赖到最新稳定版。

3. 开发 Mojo

Mojo(Maven plain Old Java Object)是插件的核心执行单元,你可以理解为一个“接口”或“任务”。一个插件可以包含多个 Mojo。

3.1 添加必要依赖

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>

✅ 依赖说明:

  • maven-plugin-api:Mojo 运行的基础 API
  • maven-plugin-annotations:支持 @Mojo@Parameter 等注解(推荐使用)
  • maven-project:用于获取宿主项目的元信息(如依赖列表)

3.2 实现 Mojo 类

创建 DependencyCounterMojo 类,继承 AbstractMojo 并实现 execute 方法:

@Mojo(name = "dependency-counter", defaultPhase = LifecyclePhase.COMPILE)
public class DependencyCounterMojo extends AbstractMojo {
    
    @Parameter(defaultValue = "${project}", required = true, readonly = true)
    MavenProject project;

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

✅ 关键点解析:

  • @Mojo(name = "dependency-counter"):定义目标名称,后续通过 mvn counter:dependency-counter 调用
  • defaultPhase = LifecyclePhase.COMPILE:绑定到编译阶段,无需显式指定 phase
  • @Parameter(defaultValue = "${project}"):Maven 自动注入当前项目对象,只读
  • getLog().info():输出日志,比 System.out 更规范

3.3 添加用户可配置参数

上面的 Mojo 只能统计所有依赖。我们来加个 scope 参数,让用户指定统计范围(如 compiletest):

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

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

✅ 参数机制说明:

  • property = "scope" 表示可通过 -Dscope=test 从命令行传参
  • 若未传参,则 scopenull,默认统计所有依赖

更复杂的参数类型(如 List、嵌套对象)可参考官方文档。

4. 插件测试

开发完成,进入验证环节。先安装到本地仓库:

mvn clean install

4.1 命令行直接调用

有两种方式运行插件:

方式一:全限定名(Always works)

mvn com.baeldung:counter-maven-plugin:0.0.1-SNAPSHOT:dependency-counter

方式二:短命名(推荐)

mvn counter:dependency-counter

⚠️ 使用短命名需确保 settings.xml 包含你的 groupId:

<pluginGroups>
    <pluginGroup>com.baeldung</pluginGroup>
</pluginGroups>

输出示例:

[INFO] --- counter-maven-plugin:0.0.1-SNAPSHOT:dependency-counter (default-cli) @ counter-maven-plugin ---
[INFO] Number of dependencies: 3

传参测试:

mvn counter:dependency-counter -Dscope=test

4.2 在项目中集成使用

创建一个测试项目 example,引入几个依赖:

<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.13.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

<build> 中配置插件:

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

✅ 注意:

  • <configuration> 中设置 scope 参数
  • 无需指定 phase,Mojo 已默认绑定 compile 阶段

执行构建:

mvn clean compile

输出:

[INFO] Number of dependencies: 1

完美,只统计了 test 范围的依赖。

📌 提示:生产级插件应编写单元测试和集成测试,Maven 提供了 maven-plugin-testing-harness 支持。

5. 生成插件文档

好插件必须配好文档。Maven 支持自动生成 HTML 文档,步骤如下:

5.1 升级并配置插件版本

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

5.2 添加项目元信息

<organization>
    <name>Baeldung</name>
    <url>https://www.baeldung.com/</url>
</organization>

5.3 启用文档报告

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

5.4 生成文档

mvn site

生成的文档位于 target/site/,其中 plugin-info.html 是核心文档页:

Screenshot-2019-11-25-at-19.15.09

✅ 文档内容会自动提取 Mojo 的 Javadoc 和参数信息,记得写好注释!

6. 总结

本文带你实战开发了一个 counter-maven-plugin,覆盖了从项目搭建、Mojo 编写、参数配置、测试验证到文档生成的完整流程。

核心收获:

  • ✅ Mojo 是插件的执行单元,通过注解配置
  • maven-plugin-annotations 极大简化开发
  • ✅ 命名规范和 groupId 配置影响调用方式
  • ✅ 自动生成文档提升可用性

虽然示例功能简单,但骨架完整。你可以基于此模板扩展更复杂的插件,比如代码生成、静态检查、部署发布等。

本文完整代码已托管至 GitHub:https://github.com/eugenp/tutorials/tree/master/maven-modules/maven-custom-plugin


原始标题:How to Create a Maven Plugin | Baeldung