自己写maven插件

本文仿制一个统计代码行数的简单插件,以此理解maven插件的工作原理。

1.建一个maven项目

注意: maven-xxx-plugin的格式是官方预留的, 我们使用的格式是xxx-maven-plugin

1
2
3
4
5
6
7
8
9
10
$ mvn archetype:generate
Define value for property 'groupId': com.jimo
Define value for property 'artifactId': jcount-maven-plugin
Define value for property 'version' 1.0-SNAPSHOT: : 1.0
Define value for property 'package' com.jimo: : com.jimo
Confirm properties configuration:
groupId: com.jimo
artifactId: jcount-maven-plugin
version: 1.0
package: com.jimo

2.修改pom文件

  1. packaging方式
  2. 增加maven-plugin-api依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<modelVersion>4.0.0</modelVersion>
<groupId>com.jimo</groupId>
<artifactId>jcount-maven-plugin</artifactId>
<version>1.0</version>
<name>count-maven-plugin</name>
<url>http://maven.apache.org</url>

<packaging>maven-plugin</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>

3.编写核心AbstractMojo实现类

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
* goal是必须的
*
* @author jimo
* @date 19-8-23 下午4:10
* @goal count
*/
public class CountMojo extends AbstractMojo {

private static final String[] INCLUDES_DEFAULT = {"java", "xml"};

/**
* @parameter property="project.basedir"
* @required
* @readonly
*/
private File baseDir;

/**
* @parameter property="project.build.sourceDirectory"
* @required
* @readonly
*/
private File sourceDirectory;

/**
* @parameter property="project.build.testSourceDirectory"
* @required
* @readonly
*/
private File testSourceDirectory;

/**
* @parameter property="project.build.resources"
* @required
* @readonly
*/
private List<Resource> resources;

/**
* @parameter property="project.build.testResources"
* @required
* @readonly
*/
private List<Resource> testResources;

/**
* 参数:包含哪些格式的文件被统计
*
* @parameter
*/
private String[] includes;

public void execute() throws MojoExecutionException, MojoFailureException {
if (includes == null || includes.length == 0) {
includes = INCLUDES_DEFAULT;
}

countDir(sourceDirectory);

countDir(testSourceDirectory);

for (Resource resource : resources) {
countDir(new File(resource.getDirectory()));
}

for (Resource testResource : testResources) {
countDir(new File(testResource.getDirectory()));
}
}

private void countDir(File dir) {
if (!dir.exists()) {
return;
}
List<File> files = new ArrayList<File>();
countFiles(files, dir);

int lines = 0;

for (File file : files) {
lines += countLine(file);
}

String path = dir.getAbsolutePath().substring(baseDir.getAbsolutePath().length());

getLog().info(path + ":" + lines + " lines of code in " + files.size() + " files");
}

private int countLine(File file) {
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
int line = 0;
while (reader.ready()) {
reader.readLine();
line++;
}
return line;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}

private void countFiles(List<File> files, File f) {
if (f.isFile()) {
for (String include : includes) {
if (f.getName().endsWith("." + include)) {
files.add(f);
break;
}
}
} else {
for (File file : f.listFiles()) {
countFiles(files, file);
}
}
}

}

注意:关于注释中的变量

  • 以前的写法是: @parameter expression="${property}",
  • 现在的写法: @parameter property="property"

4.安装插件到本地仓库

1
$ mvn clean install

5.使用

在另外的项目中使用插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugins>
<plugin>
<groupId>com.jimo</groupId>
<artifactId>jcount-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<includes>
<include>java</include>
<include>yml</include>
</includes>
</configuration>
</plugin>
</plugins>

可能的结果:

1
2
3
4
5
6
7
8
$ mvn com.jimo:jcount-maven-plugin:1.0:count
...
[INFO] --- jcount-maven-plugin:1.0:count (default-cli) @ jasypt-demo ---
[INFO] /src/main/java:18 lines of code in 1 files
[INFO] /src/test/java:22 lines of code in 1 files
[INFO] /src/main/resources:3 lines of code in 1 files
[INFO] /src/main/resources:3 lines of code in 1 files
...

参考书籍《maven实战》