0%

maven自定义插件

Maven 自定义插件开发全指南:从实现到应用

Maven 插件是扩展 Maven 功能的核心方式,通过自定义插件,你可以将团队特有的构建逻辑、检查规则或部署流程集成到 Maven 生命周期中。本文将详细介绍如何开发、打包和使用自定义 Maven 插件。

自定义插件的核心概念

  • Mojo:Maven 插件的最小执行单元(类似 “目标”),每个插件包含一个或多个 Mojo,每个 Mojo 对应一个具体功能(如代码检查、自定义打包)。
  • 插件打包类型:自定义插件必须使用 <packaging>maven-plugin</packaging> 声明。
  • 注解驱动:通过 @Mojo 注解定义 Mojo 元信息,@Parameter 注解声明可配置参数。

开发自定义插件的步骤

1. 创建插件项目

新建一个 Maven 项目,修改 pom.xml 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<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.zhanghe.study</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging> <!-- 插件必须使用此打包类型 -->

<name>Test Maven Plugin</name>
<description>A custom Maven plugin example</description>

<dependencies>
<!-- 插件核心依赖 -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.8.6</version> <!-- 推荐使用较新版本 -->
</dependency>
<!-- 注解处理器(简化 Mojo 配置) -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.4</version>
<scope>provided</scope> <!-- 编译时依赖 -->
</dependency>
</dependencies>
</project>

2. 实现 Mojo 类

每个 Mojo 类需继承 AbstractMojo 并实现 execute() 方法,通过注解定义元信息和参数。

示例:创建一个打印版本信息的 Mojo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

// 定义 Mojo 名称和默认绑定的生命周期阶段
@Mojo(
name = "printVersion", // 插件目标名称(调用时使用:printVersion)
defaultPhase = LifecyclePhase.COMPILE, // 默认在 compile 阶段执行
requiresProject = true // 必须在 Maven 项目中运行
)
public class VersionPrinterMojo extends AbstractMojo {

// 注入当前 Maven 项目信息(内置参数)
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;

// 自定义参数(可在 pom.xml 中配置)
@Parameter(
name = "prefix", // 参数名称
defaultValue = "Project Version: ", // 默认值
required = false // 非必须
)
private String prefix;

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
// 获取项目版本(来自 pom.xml 的 version 字段)
String version = project.getVersion();
// 打印信息(使用 Maven 的日志接口,而非 System.out)
getLog().info(prefix + version);
}
}
关键注解说明:
  • @Mojo:定义 Mojo 核心属性:
    • name:目标名称(如 printVersion),调用时使用 插件前缀:name
    • defaultPhase:默认绑定的生命周期阶段(如 COMPILE),可省略(需手动绑定)。
    • requiresProject:是否必须在 Maven 项目中运行(默认 true)。
  • @Parameter:定义可配置参数:
    • defaultValue:默认值,支持 Maven 表达式(如 ${project.version})。
    • property:可通过命令行 -Dproperty=value 覆盖参数(如 property = "version.prefix" 则可通过 -Dversion.prefix=XXX 配置)。
    • required:是否必须配置(未配置则报错)。
    • readonly:是否只读(用户无法在 pom 中配置,通常用于注入内置对象如 project)。

3. 打包插件到仓库

执行以下命令将插件安装到本地仓库(供本地项目使用):

1
mvn clean install

若需团队共享,可部署到私服(如 Nexus):

1
mvn clean deploy  # 需在 pom.xml 中配置 distributionManagement

在项目中使用自定义插件

在目标项目的 pom.xml 中引入自定义插件,并配置参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<build>
<plugins>
<plugin>
<!-- 插件坐标(与自定义插件的 groupId、artifactId、version 一致) -->
<groupId>com.zhanghe.study</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>

<!-- 配置插件参数 -->
<configuration>
<prefix>当前项目版本:</prefix> <!-- 覆盖默认前缀 -->
</configuration>

<!-- 绑定到生命周期阶段(若 Mojo 未指定 defaultPhase) -->
<executions>
<execution>
<phase>compile</phase> <!-- 在 compile 阶段执行 -->
<goals>
<goal>printVersion</goal> <!-- 执行自定义 Mojo -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

执行插件目标

方式 1:通过生命周期阶段(推荐)

由于插件已绑定到 compile 阶段,执行以下命令会自动触发:

1
mvn compile
方式 2:直接调用目标

无需绑定生命周期,直接通过命令行调用:

1
mvn com.zhanghe.study:test-maven-plugin:1.0-SNAPSHOT:printVersion
方式 3:配置插件前缀(简化调用)

在插件项目的 pom.xml 中配置插件前缀(需部署到仓库):

1
2
3
4
5
6
7
8
9
10
11
12
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.4</version>
<configuration>
<goalPrefix>custom</goalPrefix> <!-- 自定义前缀 -->
</configuration>
</plugin>
</plugins>
</build>

重新安装插件后,可通过前缀简化调用:

1
mvn custom:printVersion  # 等价于完整坐标调用

高级特性

1. 处理异常

Mojo 执行时可抛出两种异常:

  • MojoFailureException:预期错误(如参数无效),Maven 会显示 BUILD FAILURE
  • MojoExecutionException:非预期错误(如 IO 异常),Maven 会显示 BUILD ERROR
1
2
3
4
5
6
7
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (prefix == null || prefix.isEmpty()) {
throw new MojoFailureException("参数 'prefix' 不能为空!");
}
// ...
}

2. 注入内置对象

Maven 提供了多种可直接注入的内置对象(通过 @Parameter):

  • ${project}:当前项目信息(MavenProject 类型)。
  • ${session}:Maven 会话(MavenSession 类型)。
  • ${settings}:Maven 配置(Settings 类型)。
1
2
3
4
5
6
7
8
@Parameter(defaultValue = "${settings}", readonly = true)
private Settings settings;

@Override
public void execute() {
String localRepo = settings.getLocalRepository(); // 获取本地仓库路径
getLog().info("本地仓库位置:" + localRepo);
}

3. 多 Mojo 插件

一个插件可包含多个 Mojo 类,只需为每个类添加 @Mojo 注解并指定不同 name

1
2
3
4
@Mojo(name = "printName")
public class NamePrinterMojo extends AbstractMojo {
// ... 实现打印项目名称的逻辑
}

调用时指定不同目标:

1
2
mvn custom:printVersion  # 调用第一个 Mojo
mvn custom:printName # 调用第二个 Mojo

调试自定义插件

  1. 在插件项目中添加调试配置(以 IDEA 为例):

    • 新建 “Maven 运行 / 调试配置”。
    • 命令行输入:clean install -Dmaven.plugin.validation=VERBOSE
    • 勾选 “调试” 选项,启动调试。
  2. 在目标项目中通过远程调试:

    1
    mvn compile -Dmaven.surefire.debug  # 触发调试模式

欢迎关注我的其它发布渠道