前几天工作之余,同事让我写一个Maven插件,因为项目很多很杂,我们公司又没有专业的数据库字典管理工具,都是我们开发人员用Excel整理一个数据字典给我们现场实施人员,每次增加新功能或该需求,增加表和修改数据时,对Excel形式数据字典维护有点。。。,此文不是讲如何维护Excel而是手写maven插件,对于我需要的功能用Maven插件来实现太简单了。
那就开始。
这里只介绍用IDEA的做法,当然其他工具也可以,只是我这边用的是IDEA。
首先我们先建个mavn项目如图:
这里就是为什么我选着IDEA因为IDEA有现成的工具
然后就是填写GroupId和Version
再然后就是完成
打开项目
已经有了现成的例子了,我们就在它给的例子上做修改。
参考maven官网添加依赖以及插件
<!-- plugin API and plugin-tools --> | |
<dependency> | |
<groupId>org.apache.maven</groupId> | |
<artifactId>maven-plugin-api</artifactId> | |
<version>3.5.2</version> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.maven.plugin-tools</groupId> | |
<artifactId>maven-plugin-annotations</artifactId> | |
<version>3.5</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>com.alibaba</groupId> | |
<artifactId>easyexcel</artifactId> | |
<version>2.1.6</version> | |
</dependency> | |
<!-- 用于获取jpa注解生成对应的excel--> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-data-jpa</artifactId> | |
<version>2.2.4.RELEASE</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<plugins> | |
<plugin> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<version>3.7.0</version> | |
</plugin> | |
<plugin> | |
<artifactId>maven-install-plugin</artifactId> | |
<version>2.5.2</version> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-plugin-plugin</artifactId> | |
<version>3.5.1</version> | |
</plugin> | |
</plugins> | |
</build> |
配置算是结束了
先建类注解和属性注解两个注解类
类注解
/** | |
* @author zhuyao | |
* @description 类注解获取表名 | |
*/ | |
public TableName { | |
/** | |
* 名称 | |
* @return | |
*/ | |
String name() default ""; | |
/** | |
* 信息 | |
* @return | |
*/ | |
String message(); | |
} | |
/** | |
* @author zhuyao | |
* @description 属性注解用于获取表字段意思 | |
*/ | |
public FieldName { | |
/** | |
* 名称 | |
* @return | |
*/ | |
String name() default ""; | |
/** | |
* 信息 | |
* @return | |
*/ | |
String message(); | |
} |
然后上逻辑代码
/** | |
* @author zhuyao | |
*/ | |
//这里到引用插件的时候需要用到 | |
public class TableToExcelMavenMojo extends AbstractMojo { | |
/** | |
* 扫描包 | |
*/ | |
private String scanPackage; | |
/** | |
* 项目源码包路径 | |
*/ | |
private String[] compileClasspathElements; | |
/** | |
* 项目的artifactId | |
*/ | |
private String artifactId; | |
private URLClassLoader loader; | |
public void execute() { | |
String file = compileClasspathElements[0].replace("classes",""); | |
String classPath = compileClasspathElements[0]; | |
String libPath = compileClasspathElements[0].replace("classes",artifactId+"/WEB-INF/lib"); | |
String basePackage = compileClasspathElements[0]+"/"+scanPackage.replaceAll("\\.","/"); | |
try { | |
String libDir = (new URL("file",null,new File(libPath).getCanonicalPath()+File.separator)).toString(); | |
String baseDir = (new URL("file",null,new File(classPath).getCanonicalPath()+File.separator)).toString(); | |
File libDirFile = new File(libDir.replaceAll("file","")); | |
URLStreamHandler us = null; | |
List<URL> libs = new ArrayList<URL>(); | |
if (null!=libDirFile.listFiles()){ | |
for (File jar : libDirFile.listFiles()) { | |
libs.add(new URL(null,libDir+jar.getName(),us)); | |
} | |
} | |
libs.add(new URL(null,baseDir,us)); | |
loader = new URLClassLoader(libs.toArray(new URL[libs.size()]),Thread.currentThread().getContextClassLoader()); | |
File dir = new File(basePackage); | |
List<Class<?>> classes = new ArrayList<Class<?>>(); | |
scanner(classes,dir,classPath); | |
List<List<Object>> objectList = new ArrayList<List<Object>>(); | |
for (Class<?> aClass : classes) { | |
if ((aClass.getAnnotation(TableName.class) != null) || (aClass.getAnnotation(Table.class) != null) || (aClass.getAnnotation(Entity.class)!=null)) { | |
List<Object> list1 = new ArrayList<Object>(); | |
List<Object> list2 = new ArrayList<Object>(); | |
List<Object> list3 = new ArrayList<Object>(); | |
list1.add("表字段"); | |
if ((aClass.getAnnotation(TableName.class) != null) && isNotEmpty(aClass.getAnnotation(TableName.class).name())){ | |
list1.add(aClass.getAnnotation(TableName.class).name()); | |
}else if ((aClass.getAnnotation(Table.class) != null) && isNotEmpty(aClass.getAnnotation(Table.class).name())){ | |
list1.add(aClass.getAnnotation(Table.class).name()); | |
} else { | |
list1.add(aClass.getSimpleName().toLowerCase()); | |
} | |
list2.add("字段意思"); | |
if ((aClass.getAnnotation(TableName.class) != null) && isNotEmpty(aClass.getAnnotation(TableName.class).message())){ | |
list2.add(aClass.getAnnotation(TableName.class).message()); | |
} else { | |
list2.add("未写注释"); | |
} | |
list3.add(""); | |
Field[] declaredFields = aClass.getDeclaredFields(); | |
for (Field declaredField : declaredFields) { | |
if ((declaredField.getAnnotation(FieldName.class) != null) || (declaredField.getAnnotation(Column.class) != null)) { | |
if ((declaredField.getAnnotation(FieldName.class) != null) && isNotEmpty(declaredField.getAnnotation(FieldName.class).name())){ | |
list1.add(declaredField.getAnnotation(FieldName.class).name()); | |
}else if ((declaredField.getAnnotation(Column.class) != null) && isNotEmpty(declaredField.getAnnotation(Column.class).name())){ | |
list1.add(declaredField.getAnnotation(Column.class).name()); | |
}else { | |
list1.add(apply(declaredField.getName())); | |
} | |
if ((declaredField.getAnnotation(FieldName.class) != null)&& isNotEmpty(declaredField.getAnnotation(FieldName.class).message())){ | |
list2.add(declaredField.getAnnotation(FieldName.class).message()); | |
} else { | |
list2.add("未写注释"); | |
} | |
}else { | |
list1.add(apply(declaredField.getName())); | |
list2.add("未写注释"); | |
} | |
} | |
objectList.add(list1); | |
objectList.add(list2); | |
objectList.add(list3); | |
} | |
OutputStream out = new FileOutputStream(file + "/table.xlsx"); | |
new ExcelWriterBuilder().excelType(ExcelTypeEnum.XLSX) | |
.file(out) | |
.sheet(1,"表").table(1) | |
.doWrite(objectList); | |
out.close(); | |
} | |
} catch (IOException e){ | |
e.fillInStackTrace(); | |
} | |
} | |
private void scanner(List<Class<?>> classes,File dir,String classPath){ | |
File[] files = dir.listFiles(); | |
for (File file : files) { | |
if (file.isDirectory()){ | |
scanner(classes,file,classPath); | |
}else { | |
if (!file.getName().endsWith(".class")){ | |
continue; | |
} | |
String path = file.getPath(); | |
String className = getClassName(path,classPath); | |
try { | |
classes.add(Class.forName(className,true,loader)); | |
} catch (ClassNotFoundException e){ | |
e.printStackTrace(); | |
continue; | |
} | |
} | |
} | |
} | |
private String getClassName(String path,String classPath){ | |
classPath = (classPath==null?"":classPath); | |
String classDir = path.replaceAll("\\\\", "/") | |
.replaceAll(classPath.replaceAll("\\\\", "/"), "") | |
.replaceAll("/", ".") | |
.replaceAll("\\.class", ""); | |
String className = classDir.substring(1, classDir.length()); | |
return className; | |
} | |
/** | |
* jpa源码中的实体类如何转成数据库字段 | |
* @param name | |
* @return | |
*/ | |
private static String apply(String name) { | |
if (name == null) { | |
return null; | |
} else { | |
StringBuilder builder = new StringBuilder(name.replace('.', '_')); | |
for(int i = 1; i < builder.length() - 1; ++i) { | |
if (isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i), builder.charAt(i + 1))) { | |
builder.insert(i++, '_'); | |
} | |
} | |
return builder.toString().toLowerCase(); | |
} | |
} | |
private static boolean isUnderscoreRequired(char before, char current, char after) { | |
return Character.isLowerCase(before) && Character.isUpperCase(current) && Character.isLowerCase(after); | |
} | |
} |
到这项目需要的maven插件已经算是结束了,现在就是把它打包到中央仓库,如果你不分享给其他用只要把它放到自己的本地仓库就行了,mvn install
现在我们测试下
在项目中引入jar包和插件
<dependencies> | |
<dependency> | |
<groupId>xin.zhuyao</groupId> | |
<artifactId>table-to-excel-maven</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>xin.zhuyao</groupId> | |
<artifactId>table-to-excel-maven</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<configuration> | |
<!--扫描包--> | |
<scanPackage>xin.zhuyao.wechat_article</scanPackage> | |
</configuration> | |
<executions> | |
<execution> | |
<id>tableToExcelMaven</id> | |
<phase>prepare-package</phase> | |
<goals> | |
<!--这个就是Mojo的name--> | |
<goal>tableToExcelMaven</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
</plugins> | |
</build> |
这个插件是在打包时执行
这个项目用的是spring-data-jpa写的所以没有添加我的注解也是可以生产表格的。
现在我加上注解
打包后的得到道德excel是
这就出来了,也就是每次你在修改添加数据库实体类的时候添加注解就可以了,每次都会生成新的。是不是很神奇。其实maven插件还有更多用处,跟多方法,你可以去官网查查:http://maven.apache.org/plugins/
上面的项目地址在:https://github.com/zywaiting/table-to-excel-maven
学习永远是自己的事,别人说了再多,自己不动手也是学不到太多东西,maven插件官网已给,项目地址已给,剩下的就靠你自己了,其实我写的连这个知识点的九牛一毛都不算,在写这篇文章时我才发现,自己真的太渺小了。
(完)