作者:小傅哥
博客:https://bugstack.cn
源码:https://github.com/fuzhengwei/CodeGuide/wiki
积淀、分享、成长,让本人和别人都能有所播种!😄
一、前言
都能用,都能凑活用!
一个货色好几套,为了降职都来搞。拿了问题就要跑,前面兄弟再重造!
几年前,大家并不是这样,那时候还有很多货色能够翻新,盛世出英雄总能在一个方向深耕并作出一款款好用的产品性能、框架服务、技术组件等。但起初如同这样的状况开始缩小了,取而代之的是反复、复刻、照搬,换个新的皮肤、换个新的款式、换个新的名字,就是取巧的新货色了。
有时候公司或者组织也像家,但家里的货色个别是破了补补、坏了修修,切实不行就换个,但没有谁的家里卫生间一个马桶、厨房一个马桶、客厅一个马桶、卧室一个马桶的,尽管你的新马桶能够主动喷水。
所以,在建设一个好的产品性能时,尽可能要学学那些曾经十分的优良的产品,IDEA、GitHub、Mysql 等等,在 IDEA 提供了满足用户扩大性能的插件开发,而不是你说一个货色我没有,你就本人造。共建会让这个货色变得更加优良!
二、需要目标
在上一章节中咱们通过扩大创立工程向导,增加咱们须要创立 DDD 工程脚手架的步骤,最终提供一个 DDD 开发框架。那么在这个 DDD 工程开发框架中,还短少一部分基于数据库表信息主动生成对应 PO、DAO、Mapper 文件的性能。
- 那么本章节咱们就来在工程中扩大这部分内容,实际操作的成果就是咱们能够在工程上通过鼠标右键的形式,唤出增加 ORM 代码块的窗体,通过抉择库表的形式,应用 freemarker 主动生成代码。
- 在生成的代码块中须要实现对所须要包的引入,同时会应用到 lombok 注解的形式代替 PO 对象中的 get、set 办法,以缩小代码量逻辑的创立。
三、案例开发
1. 工程构造
guide-idea-plugin-orm
├── .gradle
└── src
├── main
│ └── java
│ └── cn.bugstack.guide.idea.plugin
│ ├── action
│ │ └── CodeGenerateAction.java
│ ├── domain
│ │ ├── model.vo
│ │ │ ├── CodeGenContextVO.java
│ │ │ └── ORMConfigVO.java
│ │ └── service
│ │ ├── impl
│ │ │ └── ProjectGeneratorImpl.java
│ │ ├── AbstractProjectGenerator.java
│ │ ├── GeneratorConfig.java
│ │ └── IProjectGenerator.java
│ ├── infrastructure
│ │ ├── data
│ │ │ ├── DataSetting.java
│ │ │ └── DataState.java
│ │ ├── po
│ │ │ ├── Base.java
│ │ │ ├── Column.java
│ │ │ ├── Dao.java
│ │ │ ├── Field.java
│ │ │ ├── Model.java
│ │ │ └── Table.java
│ │ └── utils
│ │ ├── DBHelper.java
│ │ └── JavaType.java
│ ├── module
│ │ └── FileChooserComponent.java
│ └── ui
│ ├── ORMSettingsUI.java
│ └── ORMSettingsUI.form
├── resources
│ ├── META-INF
│ │ └── plugin.xml
│ └── template
│ ├── dao.ftl
│ ├── mapper.ftl
│ └── model.ftl
├── build.gradle
└── gradle.properties
源码获取:# 公众号:bugstack 虫洞栈
回复:idea
即可下载全副 IDEA 插件开发源码# 第 5 章:在开发工程中鼠标右键,生成 ORM 代码
在此 IDEA 插件工程中,次要分为 5 块区域:
- action:用于提供菜单栏,这个菜单的地位在 plugin.xml 中配置,咱们把它配置到工程鼠标右键呈现的列表上。这样能够更加不便的让咱们选取工程,以及在这个工程下增加生成的代码片段
- domain:畛域服务层,其实你间接写一个 Service 包也是能够的,只不过最近作者小傅哥更喜爱应用 DDD 的思维和构造来创立代码实现性能逻辑。
- infrastructure:根底层,提供数据在工程下的寄存,每一个工程右键都有本人的配置存储默认信息,不便下次关上的时候能够读取到这部分内容。同时这一层还提供了用于解决数据库操作的类,因为咱们须要从数据库中读取出表的信息、字段、正文,用于创立 PO、DAO、Mapper 应用。
- module:模块层,这里提供了一个用于抉择文件门路的组件,能够让咱们在工程上鼠标右键的进去的窗体中,点击模块抉择对应的要生成代码的地位门路。
- ui:提供配置面板,也就是咱们在代码工程上鼠标右键弹出来的面板,这个面板配置后用于生成 ORM 代码。
2. 拖拽 Swing 面板
ORMSettingsUI:咱们先把用于创立代码配置的面板创立进去,有了画面,就好进入了。
- 面板包含生成 PO、DAO、XML 的代码门路,以及配置数据库和抉择表的内容。
- 操作过程就是在你配置好了这些根本信息后,就能够抉择查问表名,并抉择好你要给哪几个表生成对应的 ORM 代码了。
3. 配置鼠标右键弹窗
首先咱们须要创立一个 Action 实现类,通过 New -> Plugin DevKit -> Action
cn.bugstack.guide.idea.plugin.action.CodeGenerateAction
/**
* @author: 小傅哥,微信:fustack
* @github: https://github.com/fuzhengwei
* @Copyright: 公众号:bugstack 虫洞栈 | 博客:https://bugstack.cn - 积淀、分享、成长,让本人和别人都能有所播种!*/
public class CodeGenerateAction extends AnAction {private IProjectGenerator projectGenerator = new ProjectGeneratorImpl();
@Override
public void actionPerformed(AnActionEvent e) {Project project = e.getRequiredData(CommonDataKeys.PROJECT);
ShowSettingsUtil.getInstance().editConfigurable(project, new ORMSettingsUI(project, projectGenerator));
}
}
- 这是一个右键菜单的入口,通过这个入口能力去关上咱们本人的 UI 窗体,这个 UI 窗体就是咱们下面拖拽进去的配置面板,ORMSettingsUI
- 接下来咱们还须要把这个 Action 配置到 plugin.xml 文件中,能力被右键菜单创立进去。开发代码的时候也是这样一个流程,你总要从一个点开始,有了抓手才好抓下去
plugin.xml 配置
<actions>
<!-- Add your actions here -->
<action id="CodeGenerateAction" class="cn.bugstack.guide.idea.plugin.action.CodeGenerateAction"
text="ORMCodeGenerate - 小傅哥" description="Code Generate ORM" icon="/icons/logo.png">
<add-to-group group-id="ProjectViewPopupMenu" anchor="last"/>
</action>
</actions>
ea-plugin>
- 把咱们的 Action 实现类配置到 xml 中,同时你还要配置它应该呈现的地位,比方你须要把这个菜单增加到工程创立中
ProjectViewPopupMenu
以及地位信息anchor="last"
- 另外为了让插件看上去更加高大上还好看适宜吹牛,那么还须要配置 icon,这个地位配置一个
16*16
的图片,图片能够从 iconfont 进行下载。
4. 给窗体增加性能
这一步其实干的就是注入灵魂的事件,让窗体活起来。给输入框增加内容、给按钮增加事件、给确认按钮减少上生成创立 ORM 代码块的上下文。文章的形容尽可能会偏差于外围代码的解说,详情能够参考源码
接下来这部分内容会在 ORMSettingsUI 类中 重复摩擦,直到补全所有性能。
4.1 抉择框事件
// 抉择 PO 生成目录
this.poButton.addActionListener(e -> {FileChooserComponent component = FileChooserComponent.getInstance(project);
VirtualFile baseDir = project.getBaseDir();
VirtualFile virtualFile = component.showFolderSelectionDialog("抉择 PO 生成目录", baseDir, baseDir);
if (null != virtualFile) {ORMSettingsUI.this.poPath.setText(virtualFile.getPath());
}
});
- 还记得咱们提到的
拖拽 Swing 面板
吗,那么这个增加事件的步骤就是给你的 PO 目录增加一个事件,容许咱们能够本人抉择出要把对应 PO 的代码生成到哪个目录构造下。 - 对于 dao、xml 都是相似操作,这里就不在演示了。
4.2 数据表事件
this.selectButton.addActionListener(e -> {
try {DBHelper dbHelper = new DBHelper(this.host.getText(), Integer.parseInt(this.port.getText()), this.user.getText(), this.password.getText(), this.database.getText());
List<String> tableList = dbHelper.getAllTableName(this.database.getText());
String[] title = {""," 表名 "};
Object[][] data = new Object[tableList.size()][2];
for (int i = 0; i < tableList.size(); i++) {data[i][1] = tableList.get(i);
}
table1.setModel(new DefaultTableModel(data, title));
TableColumn tc = table1.getColumnModel().getColumn(0);
tc.setCellEditor(new DefaultCellEditor(new JCheckBox()));
tc.setCellEditor(table1.getDefaultEditor(Boolean.class));
tc.setCellRenderer(table1.getDefaultRenderer(Boolean.class));
tc.setMaxWidth(100);
} catch (Exception exception) {Messages.showWarningDialog(project, "数据库连贯谬误, 请查看配置.", "Warning");
}
});
- 这一步操作外围流程就在于把你须要生成 ORM 的代码的表给拉进去,只有把表抉择上,能力依据表生成 PO、DAO、Mapper,其实你用的其余一些主动生成代码框架也是这么干的。
- 另外你的建表最好标准,比方有表正文、有字段正文、字段的设计恪守下划线和小写字母,这样会更加容易创立出难看的代码。
4.3 组装生成代码上下文
当咱们点击配置窗体的 OK 按钮时候,要干啥,对喽,咱们要创立出代码片段了,那么这个时候须要在重写的 apply
中实现此项操作。
public void apply() {
// 链接 DB
DBHelper dbHelper = new DBHelper(config.getHost(), Integer.parseInt(config.getPort()), config.getUser(), config.getPassword(), config.getDatabase());
// 组装代码生产上下文
CodeGenContextVO codeGenContext = new CodeGenContextVO();
codeGenContext.setModelPackage(config.getPoPath() + "/po/");
codeGenContext.setDaoPackage(config.getDaoPath() + "/dao/");
codeGenContext.setMapperDir(config.getXmlPath() + "/mapper/");
List<Table> tables = new ArrayList<>();
Set<String> tableNames = config.getTableNames();
for (String tableName : tableNames) {tables.add(dbHelper.getTable(tableName));
}
codeGenContext.setTables(tables);
// 生成代码
projectGenerator.generation(project, codeGenContext);
}
- 在 apply 中的外围代码次要就是应用 DBHelper 数据操作工具获取到对应的库下链接信息,同时把抉择的号的表创立出用于生成代码类的参数,比方;类的名称、字段名称、正文名称等。
- 最初就是调用生成代码的服务了,
projectGenerator.generation(project, codeGenContext);
这一部分就是在咱们畛域服务 domain 中实现的。
5. 代码生成畛域服务
- 用于创立 PO、DAO、Mapper 的代码块的代码次要是这里实现的,外围在于提供了一个抽象类以及对应的实现类,因为解决代码生成须要应用到 freemarker 所以就在抽象类里包装了下,这样能够免去实现类中还须要关怀这部分逻辑。
ProjectGeneratorImpl 生成代码
@Override
protected void generateORM(Project project, CodeGenContextVO codeGenContext) {List<Table> tables = codeGenContext.getTables();
for (Table table : tables) {List<Column> columns = table.getColumns();
List<Field> fields = new ArrayList<>();
for (Column column : columns) {Field field = new Field(column.getComment(), JavaType.convertType(column.getType()), column.getName());
field.setId(column.isId());
fields.add(field);
}
// 生成 PO
Model model = new Model(table.getComment(), codeGenContext.getModelPackage() + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getName()), table.getName(), fields);
writeFile(project, codeGenContext.getModelPackage(), model.getSimpleName() + ".java", "domain/orm/model.ftl", model);
// 生成 DAO
Dao dao = new Dao(table.getComment(), codeGenContext.getDaoPackage() + "I" + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getName()) + "Dao", model);
writeFile(project, codeGenContext.getDaoPackage(), dao.getSimpleName() + ".java", "domain/orm/dao.ftl", dao);
// 生成 Mapper
writeFile(project, codeGenContext.getMapperDir(), dao.getModel().getSimpleName() + "Mapper.xml", "domain/orm/mapper.ftl", dao);
}
}
- 创立代码的过程就比较简单了,通过循环提取进去的表信息,映射成对应的类和属性以及正文,再应用 resources 下的 ftl 文件创建出对应的类和 xml 配置文件就能够了。
- 如果你还须要生成起来代码片段或者创立调用一些罕用的组件,也是能够通过这样的形式进行实现的。
四、测试验证
- 点击
Plugin
启动 IDEA 插件,之后在工程右键如下:
1. 鼠标右键,抉择菜单
2. 配置页面,配置信息
3. 主动创立,生成代码
- 好了,抉择代码块就这么嗖的创立了进去,是不是十分不便,而且能够满足你在任何时候的把新的库表代码补充进来,缩小了手敲 CRUD 操作。
五、总结
- 本章节小傅哥带着你又在 IDEA DDD 插件生成工程的构造下,又欠缺了一步生成 ORM 代码,当然你也能够在创立工程向导中增加生成 ORM 代码的步骤。而在工程下创立 ORM 的形式能够当做是对脚手架工程的补充,满足不同场景下的需要。
- 此外在 IDEA 插件开发的系列内容中咱们是一直的尝试应用新的形式欠缺不同的性能点,如果你须要开发一个残缺的插件那么能够联合这些性能一起来开发你的需要。
- 插件开发中还是有很多的内容须要理解和学习的,同时也要留神一些代码实现细节,例如咱们本章节中的数据保留是在一个什么维度,是 IDEA 开发工具维度,还是在 IDEA 中的工程维度,这些是有区别。比方你的不同工程,是不须要保留同一份配置的
六、系列举荐
- 开发一个能够在 IDEA 中摸鱼看书的插件
- 方案设计:基于 IDEA 插件开发和字节码插桩技术,实现研发交付品质主动剖析
- 技术扫盲:对于低代码编程的可持续性交付设计和剖析
- 💥 🎁 Lottery 抽奖零碎 – 基于畛域驱动设计的四层架构的互联网分布式开发实际
- 《SpringBoot 中间件设计和开发》| 对,年底教你造火箭!