聊一聊 maven 生命周期和 maven 插件编写

原文:https://juejin.cn/post/6919490393893502984

最近接到一个业务同学的诉求:用户会在他们大数据平台新建很多模型表,但是再编写业务代码时,需要手动的去创建和模型表对应的 DO 类,那对于有少量表的情况还可以接受,但是对于十几张甚至几十张表的情况,就会很头疼。

我们知道 mybatis 实际上是有提供类似插件工具(mybatis-generator)的,社区也有非常多类似的代码生成工具,但是受限于一些情况,没有办法采用它们,那最简单的就是自己写个插件来完成这种工作量大且重复性高的事情。

maven 大家一定都不陌生,这篇文章不对 maven 中的一些概念和插件生命周期进行说明,网上资料很多,仅记录如何去如何编写一个 maven 插件。

maven 插件和普通的 maven 项目的区别不大,它也有自己的 GAV。区别在于, 每一个 maven 插件会包含了一些列的 goal,每一个 goal 对应于一个 Mojo 类,这个 Mojo 类需要实现org.apache.maven.plugin.Mojo 这个接口,Mojo 接口中提供了一个需要子类实现的 execute 方法。在实际的开发插件工作中,我们的任务其实就是实现这个 execute 方法里面的逻辑,在 execute 方法中去把插件需要做的事情处理好。下面先简单介绍下 maven 里面的一些基本知识:生命周期、阶段、goal,最后再来写一个 maven 插件。

maven 生命周期

Maven 构建遵循特定的生命周期来部署和分发目标项目,maven 中有三个内置的生命周期:

  • default:负责项目部署的主要生命周期
  • clean:清理上一次 build 产生的所有的文件(target/)
  • site:创建项目的站点文档

每个生命周期由一系列阶段组成;默认的构建生命周期包括 23 个阶段,这些是主要的构建生命周期。另一方面,clean 生命周期由 3 个阶段组成,而 site 生命周期由4个阶段组成。下面详细说下这些阶段。

maven 阶段

Maven 阶段表示 Maven 构建生命周期中的各个阶段,每个阶段负责一个特定的任务,默认的包括以下这些:

  • validate:检查构建所需的所有信息是否都可用
  • compile:编译源代码
  • test-compile:编译测试源代码
  • test:运行单元测试
  • package:打包(产物常见的如:jar, war,…)
  • integration-test:集成测试
  • install:将包安装到本地存储库
  • deploy:将包 deploy 到远程存储库

maven 中的阶段是有先后顺序只分的,当运行靠后的阶段时,前面的也会执行,但是也可以通过一些参数来跳过一些操作,最常见的就是 skipTests 。

比如,当我们执行

1
mvn install

可以看到,compile、test 等比较靠前的阶段也都被执行了。

maven goal

生命周期中会有阶段,阶段中会有一些列目标,每个目标负责一个特定的任务;当我们运行一个阶段时,默认会绑定到这个阶段的所有目标都按顺序执行。下面以 compile 为例:

以下是一些与之相关的阶段和默认目标:

  • compile:compile -> 编译器插件的编译目标绑定到编译阶段
  • compile:testCompile -> 被绑定到测试编译阶段

怎么去看特定阶段的目标和他的插件信息呢?mvn help:describe -Dcmd=PHASENAME,比如:

1
mvn help:describe -Dcmd=compile
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
[INFO] 'compile' is a phase corresponding to this plugin:
org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

It is a part of the lifecycle for the POM packaging 'jar'. This lifecycle includes the following phases:
* validate: Not defined
* initialize: Not defined
* generate-sources: Not defined
* process-sources: Not defined
* generate-resources: Not defined
* process-resources: org.apache.maven.plugins:maven-resources-plugin:2.6:resources
* compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
* process-classes: Not defined
* generate-test-sources: Not defined
* process-test-sources: Not defined
* generate-test-resources: Not defined
* process-test-resources: org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
* test-compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
* process-test-classes: Not defined
* test: org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
* prepare-package: Not defined
* package: org.apache.maven.plugins:maven-jar-plugin:2.4:jar
* pre-integration-test: Not defined
* integration-test: Not defined
* post-integration-test: Not defined
* verify: Not defined
* install: org.apache.maven.plugins:maven-install-plugin:2.4:install
* deploy: org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy

编写一个插件

编写一个插件大体可以分为以下几步:

step1:新建一个 maven-archetype-mojo

step2:添加一个 mojo 类

1
2
3
4
5
6
@Mojo(name = "build-glmapper", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME, requiresDependencyCollection = ResolutionScope.RUNTIME)
public class RepackageMojo extends AbstractMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("this is a test case for mojo");
}
}

step3:pom.xml 处理

pom 里面,首先是 packaging 不是 pom 也不是 jar,而是

1
<packaging>maven-plugin</packaging>

引入一些必要的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-common-artifact-filters</artifactId>
</dependency>

引入打包插件的 plugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.5</version>
<configuration>
<mojoDependencies>
<!-- plugin 的名字 -->
<dependency>com.bridge.glmapper.boot:glmapper-plugin</dependency>
</mojoDependencies>
</configuration>

</plugin>
</plugins>
</build>

step4:install 你的插件 & 测试插件允许

引入的工程中通过 maven plugin 菜单也能看到:

这里有个小细节,就是执行插件的阶段,比如我们的插件名字是 glmapper-plugin,但是实际上执行时使用的是 glmapper,也就是当插件名满足:xxx-maven-pluginmaven-xxx-plugin命名规则时,可以直接使用 xxx,即可。

总结

本文简单介绍了下 maven 的一些基础知识,以供备忘,也通过一个小 case 介绍了如何编写一个 maven plugin,如果你觉得还不错,欢迎点赞支持!!!

聊一聊 maven 生命周期和 maven 插件编写

http://www.glmapper.com/2021/01/19/maven/maven-plugin-lifecycle-program/

作者

卫恒

发布于

2021-01-19

更新于

2022-04-24

许可协议

评论