如何3分鐘,快速開發一個新功能

背景

關於爲什麼做這個代碼生成器,其實主要有兩點:

  1. 參與的項目中有很多分析報表需要展示給業務部門,公司使用的商用產品,或多或少有些問題,這部分可能是歷史選型導致的,這裏撇開不不談;
  2. 項目裏面也有很多CRUD的功能,而這些功能的實現代碼基本上差不多,這些功能都去手寫,也比較浪費時間而且效率很低,還可能會寫錯;

針對這兩個問題,就思考做一個簡單的半自動的代碼生成器,幫助團隊的提升開發效率,只要在數據庫中設計好表結構,就可以一鍵生成前後端代碼、Swagger接口文檔 、Validator參數校驗。

設計

此篇主要是聊聊關於單表CRUD代碼生成器的實現,後續大家可以擴展到樹表、主子表,甚至還可以接入一些AI來擴展一下。整體技術方案,後端採用Spring Boot、Freemarker、MybatisPlus、Swagger等,前端使用Vue3、Element Plus。看到這裏我想很多後端就知道我是如何做的了,整體核心實現就是通過Freemarker模版,增加一些配置項,動態生成CRUD的代碼。這裏做了一些細化設計,首先來看下整體的一個界面效果。 image.png image.png image.png image.png

表結構設計

核心設計不變,只是增加三張表,可以進行自定義配置,讓整個流程更加絲滑,整體表結構設計如下: image.png 三張表分別是數據源配置表(tool_data_source_config)、表定義(tool_generator_table)以及列定義(tool_generator_column),數據源配置表主要是連接數據庫相關的配置,表定義主要是類的抽象,包括整個類的包結構目錄,列定義主要類字段的定義,並且包含一些CRUD條件定義。通過這三張表的定義,就可以實現半自動化代碼生成。

代碼設計

整體設計分爲兩部分,一部分通過MyBatis Plus Generator讀取數據源配置,獲取對應表的TableInfo信息,最終映射到表定義和列定義的表中,另外一部分就是通過Freemarker定義模板生成對應前端和後端代碼。這裏需要注意的是每個表名定義都是模塊名加自身的業務抽象。 image.png 給大家看下核心代碼,以下代碼是通過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,下圖截圖是核心代碼的重要實現的類。 image.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章