maven插件你了解吗?自己写过maven插件吗?

Java
296
0
0
2024-02-29
标签   Maven

前几天工作之余,同事让我写一个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 类注解获取表名
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {

    /**
     * 名称
     * @return
     */
    String name() default "";

    /**
     * 信息
     * @return
     */
    String message();
}
/**
 * @author zhuyao
 * @description 属性注解用于获取表字段意思
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldName {

    /**
     * 名称
     * @return
     */
    String name() default "";

    /**
     * 信息
     * @return
     */
    String message();
}

然后上逻辑代码

/**
 * @author zhuyao
 */
@Mojo(name = "tableToExcelMaven")//这里到引用插件的时候需要用到
public class TableToExcelMavenMojo extends AbstractMojo {
    /**
     * 扫描包
     */
    @Parameter(property = "scanPackage",defaultValue = "")
    private String scanPackage;
    /**
     * 项目源码包路径
     */
    @Parameter(defaultValue = "${project.compileClasspathElements}", readonly = true)
    private String[] compileClasspathElements;
    /**
     * 项目的artifactId
     */
    @Parameter(defaultValue = "${project.artifactId}", readonly = true)
    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插件官网已给,项目地址已给,剩下的就靠你自己了,其实我写的连这个知识点的九牛一毛都不算,在写这篇文章时我才发现,自己真的太渺小了。

(完)