背景
關於爲什麼做這個代碼生成器,其實主要有兩點:
參與的項目中有很多分析報表需要展示給業務部門,公司使用的商用產品,或多或少有些問題,這部分可能是歷史選型導致的,這裏撇開不不談; 項目裏面也有很多CRUD的功能,而這些功能的實現代碼基本上差不多,這些功能都去手寫,也比較浪費時間而且效率很低,還可能會寫錯;
針對這兩個問題,就思考做一個簡單的半自動的代碼生成器,幫助團隊的提升開發效率,只要在數據庫中設計好表結構,就可以一鍵生成前後端代碼、Swagger接口文檔 、Validator參數校驗。
設計
此篇主要是聊聊關於單表CRUD代碼生成器的實現,後續大家可以擴展到樹表、主子表,甚至還可以接入一些AI來擴展一下。整體技術方案,後端採用Spring Boot、Freemarker、MybatisPlus、Swagger等,前端使用Vue3、Element Plus。看到這裏我想很多後端就知道我是如何做的了,整體核心實現就是通過Freemarker模版,增加一些配置項,動態生成CRUD的代碼。這裏做了一些細化設計,首先來看下整體的一個界面效果。
表結構設計
核心設計不變,只是增加三張表,可以進行自定義配置,讓整個流程更加絲滑,整體表結構設計如下: 三張表分別是數據源配置表(tool_data_source_config)、表定義(tool_generator_table)以及列定義(tool_generator_column),數據源配置表主要是連接數據庫相關的配置,表定義主要是類的抽象,包括整個類的包結構目錄,列定義主要類字段的定義,並且包含一些CRUD條件定義。通過這三張表的定義,就可以實現半自動化代碼生成。
代碼設計
整體設計分爲兩部分,一部分通過MyBatis Plus Generator讀取數據源配置,獲取對應表的TableInfo信息,最終映射到表定義和列定義的表中,另外一部分就是通過Freemarker定義模板生成對應前端和後端代碼。這裏需要注意的是每個表名定義都是模塊名加自身的業務抽象。 給大家看下核心代碼,以下代碼是通過MyBatis Plus Generator獲取TableInfo,TableInfo包含數據庫表的定義,後需要主要使用tableName、columns、tableComment等相關的屬性,轉換爲tool_generator_table和tool_generator_column表相關的內容;
private List<TableInfo> getAllTable(Long dataSourceConfigId, String tableName) {
// 獲得數據源配置
ToolDataSourceConfig config =
dataSourceConfigService.getDataSourceConfig(dataSourceConfigId);
// 使用 MyBatis Plus Generator 解析表結構
DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(config.getUrl(), config.getUsername(),
config.getPassword()).build();
StrategyConfig.Builder strategyConfig = new StrategyConfig.Builder();
if (StringUtils.isNotEmpty(tableName)) {
strategyConfig.addInclude(tableName);
}
GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build();
ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(),
null, globalConfig, null);
List<TableInfo> tables = builder.getTableInfoList();
tables.sort(Comparator.comparing(TableInfo::getName));
return tables;
}
以下代碼是通過Freemarker生成對應的模版,具體的細節部分,可以在GitHub上查看;
public Map<String, String> execute(ToolGeneratorTable table, List<ToolGeneratorColumn> columns) {
//初始化
Map<String, Object> bindingMap = initBindingMap(table, columns);
//獲取對應模版
Map<String, String> templates = getTemplates();
Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(templates.size());
templates.forEach((key, value) -> {
generateCode(result, key, value, bindingMap);
});
return result;
}
private void generateCode(Map<String, String> result, String vmPath, String filePath, Map<String, Object> bindingMap) {
filePath = formatFilePath(filePath, bindingMap);
try {
StringWriter writer = new StringWriter();
Template template = configuration.getTemplate(vmPath);
template.process(bindingMap, writer);
result.put(filePath, writer.toString());
} catch (Exception exception) {
log.error(vmPath + "模版加載異常" + exception);
}
}
結束
GIt地址 歡迎大家Star,下圖截圖是核心代碼的重要實現的類。