IDEA Plugin开发-通过自带数据库插件生成文件

1,207 阅读3分钟

这次的主要灵感来源于EasyCode这个插件,可以通过Idea的数据库插件生成出实体类,非常方便,这里放一下官方的介绍图

单表代码生成.gif

可以看到插件为了通用性,牺牲了一些易用性。我们日常在公司里开发的项目的目录、代码风格大多是比较固定的,如果可以定制化,把很多配置写死的话,岂不美哉!

获取数据库表信息

首先要解决的问题就是如何获取到数据库表的信息

public static DbTable getDbTable(AnActionEvent anActionEvent) {
    return (DbTable) anActionEvent.getData(LangDataKeys.PSI_ELEMENT);
}

同样也可以根据这个类型,判断action是否显示

@Override
public void update(@NotNull AnActionEvent anActionEvent) {
    PsiElement psiElement = anActionEvent.getData(LangDataKeys.PSI_ELEMENT);
    //通过这个方式控制插件是否显示和生效
    anActionEvent.getPresentation().setEnabledAndVisible(psiElement instanceof DbTable);
}

在获取到表信息之后,通过下图的方式获取到列的属性

public static List<DasColumn> getDasColumnList(DbTable dbTable) {
    return new ArrayList<>(DasUtil.getColumns(dbTable).toList());
}

DasColumn类里面可以获取到表的属性信息,比如通过getName()方法可以获取到属性名、getComment()可以获取到注释等

Freemarker模版

生成文件的模版采用Freemarker,此时需要一个配置类

public class FreemarkerMybatisConfiguration extends Configuration {

    //入参是resource下的路径
    public FreemarkerMybatisConfiguration(String basePackagePath) {
        super(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        setDefaultEncoding("UTF-8");
        setClassForTemplateLoading(getClass(), basePackagePath);
    }

    public Template getTemplate(String ftl) throws IOException {
        return this.getTemplate(ftl, "UTF-8");
    }
}

这边放一下我自己用的模版,其实大概就是循环数据库字段,生成java类,可以自行补充上包名,注释之类的信息

package ${packageInfo};

import lombok.Data;

import java.util.Date;

/**
* ${classInfo.comment}
*/
@Data
public class ${classInfo.name} {

<#list fieldInfoList as value>
 /**
 * ${value.comment}
 */
 private ${value.type} ${value.name};
</#list>
}

生成文件

为了方便阅读,略去了一些try catch

大致思路如下

  1. 初始化模版并通过模版生成类的信息
  2. 写文件
  3. 格式化(生成的类,IDEA是有现成的工具来格式化的,所以其实我们也不用太在意模版的格式信息)
/**
 * templateName: 模版名称(模版路径位置)
 * param: 模版中定义的参数
 * path: 文件生成的地址
 * fileName: 最后生成的文件名称
 */
public static boolean writeByFreemarker(Project project, String templateName, Object param, String path, String fileName) {
    //初始化并获取模版
    FreemarkerMybatisConfiguration freemarkerMybatisConfiguration = new FreemarkerMybatisConfiguration("/template/mybatis");
    Template template = freemarkerMybatisConfiguration.getTemplate(templateName);
    //生成根据模版生成java类
    StringWriter stringWriter = new StringWriter();
    template.process(param, stringWriter);
    boolean mkdirs = new File(path).mkdirs();
    //写文件
    VirtualFile virtualFile = Objects.requireNonNull(LocalFileSystem.getInstance().refreshAndFindFileByPath(path)).createChildData(project, fileName);
    virtualFile.setBinaryContent(stringWriter.toString().getBytes(StandardCharsets.UTF_8));
    PsiFile file = PsiManager.getInstance(project).findFile(virtualFile);
    //通过这个方式可以直接格式化代码,所以模版里可以不用太在意格式信息
    ReformatCodeProcessor reformatCodeProcessor = new ReformatCodeProcessor(project, file, null, false);
    reformatCodeProcessor.run();
    //理论上应该会整理导入包的,但是不知道为啥没成功。。。
    JavaCodeStyleManager.getInstance(project).optimizeImports(Objects.requireNonNull(file));
    return true;
}

生成文件的位置

设置文件生成到哪个目录,每个项目都不太一样,还是需要选择一下,IDEA提供了一个包选择器,用起来也非常简单

image.png

PackageChooserDialog packageChooserDialog = new PackageChooserDialog("Package Chooser", event.getProject());
packageChooserDialog.show();
PsiPackage selectedPackage = packageChooserDialog.getSelectedPackage();

selectedPackage就是我们最后选择的包

获取到PsiPackage之后,可以通过这种方式获取到包的绝对路径(不同模块可能会有同名的包,所以是个数组)

selectedPackage.getDirectories()[0].getVirtualFile().getPresentableUrl()

完成!

到这里其实关键的问题就都解决掉了,总步骤大概分为这几点

  1. 通过数据库插件获取到数据库表信息
  2. 将收集到的数据库信息转化为我们自己定义的模版中的属性
  3. 初始化模版,并在指定路径下生成文件

关键的代码在文中都已经提到啦,如果想看完整的代码的话可以下载源码

笨天才的代码仓库

附一张最终效果图

gifmk3953.gif

(不知道为啥IDEA报了个错,哈哈哈哈)

本文的内容到这里就结束了,如果觉得有用的话,记得点个赞呀!