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> <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( name = "printVersion", // 插件目标名称(调用时使用:printVersion) defaultPhase = LifecyclePhase.COMPILE, // 默认在 compile 阶段执行 requiresProject = true // 必须在 Maven 项目中运行 ) public class VersionPrinterMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true) private MavenProject project;
@Parameter( name = "prefix", // 参数名称 defaultValue = "Project Version: ", // 默认值 required = false // 非必须 ) private String prefix;
@Override public void execute() throws MojoExecutionException, MojoFailureException { String version = project.getVersion(); 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. 打包插件到仓库
执行以下命令将插件安装到本地仓库(供本地项目使用):
若需团队共享,可部署到私服(如 Nexus):
在项目中使用自定义插件
在目标项目的 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>com.zhanghe.study</groupId> <artifactId>test-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <configuration> <prefix>当前项目版本:</prefix> </configuration> <executions> <execution> <phase>compile</phase> <goals> <goal>printVersion</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
|
执行插件目标
方式 1:通过生命周期阶段(推荐)
由于插件已绑定到 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. 处理异常
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 mvn custom:printName
|
调试自定义插件
在插件项目中添加调试配置(以 IDEA 为例):
- 新建 “Maven 运行 / 调试配置”。
- 命令行输入:
clean install -Dmaven.plugin.validation=VERBOSE。
- 勾选 “调试” 选项,启动调试。
在目标项目中通过远程调试:
1
| mvn compile -Dmaven.surefire.debug
|