确认

  • [X] 我的版本是最新版本, 我的版本号与 version 相同, 并且项目里无依赖冲突
  • [X] 我已经在 issue 中搜索过, 确认问题没有被提出过
  • [X] 我已经修改标题, 将标题中的 描述 替换为遇到的问题

功能改进

需求假想:生成的代码不需要变成文件形式,需要将生成的代码内容显示给前端 问题: 无法使用MybatisPlus自带的代码生成进行取得生成的文本 1. 将代码生成器的配置变成一个类 --- 可以自己实现 2. 运行代码生成主方法之后是否可以增加禁止生成文件的配置 --- 禁止生成文件 3. 如何获得配置完成之后 write中 getObjectMap()方法 拿到map --- 拿到之后可以使用自定义模板引擎,生成代码并取得生成的文本

参考资料

No response

Comment From: DuYiFan01

我花时间写了一个出来,有很多不是很懂,依葫芦画瓢弄出来的,希望可以有更好的解决方式 `package cn.anlucky.system.gen;

import cn.anlucky.system.base.controller.BaseController; import cn.anlucky.system.utils.VelocityUtils; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.; import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder; import com.baomidou.mybatisplus.generator.config.builder.CustomFile; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine; import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine; import com.baomidou.mybatisplus.generator.fill.Column; import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.jetbrains.annotations.NotNull; import java.io.StringWriter; import java.util.;

/* * MybatisPlus代码生成配置 / public class MybatisPlusGenerationConfig { private static CodeGenerationConfig config;

public MybatisPlusGenerationConfig() {
    config = new CodeGenerationConfig();
}

/**
 * 获取数据源配置
 *
 * @return
 */
private DataSourceConfig.Builder getDataSourceConfigBuilder() {
    String dbUrl = config.getDbUrl();
    String dbUserName = config.getDbUserName();
    String dbPassword = config.getDbPassword();
    return new DataSourceConfig.Builder(dbUrl, dbUserName, dbPassword)
            .schema("mybatis-plus") // 数据库 schema(部分数据库适用)
            .keyWordsHandler(new MySqlKeyWordsHandler()); // 数据库关键字处理器
}

/**
 * 获取全局配置
 *
 * @return
 */
private GlobalConfig.Builder getGlobalConfigBuilder() {
    String outputDirectory = config.getOutputDirectory();
    String author = config.getAuthor();
    return new GlobalConfig.Builder()
            .disableOpenDir() // 允许自动打开输出目录
            .outputDir(outputDirectory) // 设置输出目录
            .author(author) // 设置作者名
            .enableSpringdoc() // 开启 Swagger 模式
            .dateType(DateType.TIME_PACK) // 设置时间类型策略
            .commentDate("yyyy-MM-dd HH:mm:ss");
}

/**
 * 获取包配置
 * @return
 */
private PackageConfig.Builder getPackageConfigBuilder() {
    String packagePath = config.getPackagePath();
    String packageName = config.getPackageName();
    return new PackageConfig.Builder()
            .parent(packagePath) // 设置父包名
            .moduleName(packageName) // 设置父包模块名
            .entity("pojo") // 设置 Entity 包名
            .service("service") // 设置 Service 包名
            .serviceImpl("service.impl") // 设置 Service Impl 包名
            .mapper("mapper") // 设置 Mapper 包名
            .xml("mapper") // 设置 Mapper XML 包名
            .controller("controller"); // 设置 Controller 包名
}

/**
 * 获取策略配置
 * @param tableName
 * @return
 */
private StrategyConfig getStrategyConfigBuilder(String tableName) {
    String createTimeField = config.getCreateTimeField();
    String updateTimeField = config.getUpdateTimeField();
    String deleteFlagField = config.getDeleteFlagField();
    String createByField = config.getCreateByField();
    String updateByField = config.getUpdateByField();
    return new StrategyConfig.Builder()
            .addInclude(tableName) // 设置要生成的表名
            .enableCapitalMode() // 开启大写命名
            .enableSkipView() // 开启跳过视图
            .disableSqlFilter() // 禁用 SQL 过滤
            .entityBuilder() // 实体策略
            .logicDeleteColumnName(deleteFlagField)
            .enableFileOverride()
            .enableLombok()
            .enableTableFieldAnnotation()
            .naming(NamingStrategy.underline_to_camel)
            .columnNaming(NamingStrategy.underline_to_camel)
            .addTableFills(
                    new Column(createTimeField, FieldFill.INSERT),
                    new Column(updateTimeField, FieldFill.INSERT_UPDATE),
                    new Column(createByField, FieldFill.INSERT),
                    new Column(updateByField, FieldFill.INSERT_UPDATE)
            )
            .logicDeleteColumnName("del_flag")
            .formatFileName("%s")
            .javaTemplate("/templates/java/entity.java")
            // .disable() // 禁用实体类生成
            .serviceBuilder() // service 策略
            .enableFileOverride()
            .superServiceClass(ConstVal.SUPER_SERVICE_CLASS)
            .superServiceImplClass(ConstVal.SUPER_SERVICE_IMPL_CLASS)
            .formatServiceFileName("%sService")
            .formatServiceImplFileName("%sServiceImp")
            .serviceTemplate("/templates/java/service.java")
            .serviceImplTemplate("/templates/java/serviceImpl.java")
            // .disableService() // 禁用 Service 层生成
            .mapperBuilder() // mapper 策略
            .enableFileOverride()
            .superClass(ConstVal.SUPER_MAPPER_CLASS)
            .enableBaseResultMap()
            .enableBaseColumnList()
            .formatMapperFileName("%sMapper")
            .formatXmlFileName("%sMapper")
            .mapperTemplate("/templates/java/mapper.java")
            .mapperXmlTemplate("/templates/xml/mapper.xml")
            .controllerBuilder() // controller 策略
            .superClass(BaseController.class)
            .enableFileOverride()
            .enableHyphenStyle()
            .enableRestStyle()
            .formatFileName("%sController")
            .template("/templates/java/controller.java")
            .build();
}

/**
 * 获取注入配置
 * @return
 */
private InjectionConfig.Builder getInjectionConfigBuilder(String tableName) {
    CustomFile vue = new CustomFile.Builder()
            .fileName("/index.vue")
            .templatePath("/templates/vue/index.vue.vm")
            .packageName("vue")
            .enableFileOverride().build();
    CustomFile js = new CustomFile.Builder()
            .fileName("/" + tableName + ".js")
            .templatePath("/templates/js/index.js.vm")
            .packageName("js")
            .enableFileOverride().build();
    CustomFile sql = new CustomFile.Builder()
            .fileName("/" + tableName + ".sql")
            .templatePath("/templates/sql/menus.sql.vm")
            .packageName("sql")
            .enableFileOverride().build();
    List<CustomFile> customFiles = new ArrayList<>();
    customFiles.add(vue);
    customFiles.add(js);
    customFiles.add(sql);
    return new InjectionConfig.Builder()
            .customFile(customFiles)
            .beforeOutputFile((tableInfo, objectMap)->{
                // 可以在这里添加自定义逻辑,如修改 objectMap 中的配置
            });
}

/**
 * 获取模板引擎
 * @return
 */
public AbstractTemplateEngine getTemplateEngine() {
    return new VelocityTemplateEngine() ;
}


/**
 * 指定表代码生成
 * @param tableName
 */
public void generationCode(String tableName) {
    new AutoGenerator(this.getDataSourceConfigBuilder().build())
            .global(this.getGlobalConfigBuilder().build())
            .packageInfo(this.getPackageConfigBuilder().build())
            .strategy(this.getStrategyConfigBuilder(tableName))
            .injection(this.getInjectionConfigBuilder(tableName).build())
            .execute(this.getTemplateEngine());
}

/**
 * 预览代码
 * @param tableName
 * @return
 */
public Map<String,String> previewCode(String tableName) {

    ConfigBuilder configBuilder = new ConfigBuilder(
            this.getPackageConfigBuilder().build(),
            this.getDataSourceConfigBuilder().build(),
            this.getStrategyConfigBuilder(tableName),
            null,
            this.getGlobalConfigBuilder().build(),
            this.getInjectionConfigBuilder(tableName).build());

    List<TableInfo> tableInfoList = configBuilder.getTableInfoList();
    TableInfo tableInfo = tableInfoList.get(0);
    Map<String, Object> objectMap = getObjectMap(configBuilder,tableInfo);
    VelocityContext context = new VelocityContext(objectMap);
    VelocityEngine velocityEngine = init(configBuilder);
    List<String> templatePathList = VelocityUtils.getTemplateList();

    // 创建模板文件返回给前端
    Map<String, String> map = new LinkedHashMap<>();

    for (String templatePath : templatePathList) {
        Template template = velocityEngine.getTemplate(templatePath, "UTF-8");
        String name = template.getName();
        StringWriter writer = new StringWriter();
        template.merge(context, writer);
        String string = writer.toString();
        map.put(name, string);
    }

    return map;
}

private @NotNull Map<String, Object> getObjectMap(@NotNull ConfigBuilder config, @NotNull TableInfo tableInfo) {
    StrategyConfig strategyConfig = config.getStrategyConfig();
    Map<String, Object> controllerData = strategyConfig.controller().renderData(tableInfo);
    Map<String, Object> objectMap = new HashMap(controllerData);
    Map<String, Object> mapperData = strategyConfig.mapper().renderData(tableInfo);
    objectMap.putAll(mapperData);
    Map<String, Object> serviceData = strategyConfig.service().renderData(tableInfo);
    objectMap.putAll(serviceData);
    Map<String, Object> entityData = strategyConfig.entity().renderData(tableInfo);
    objectMap.putAll(entityData);
    objectMap.put("config", config);
    objectMap.put("package", config.getPackageConfig().getPackageInfo());
    GlobalConfig globalConfig = config.getGlobalConfig();
    objectMap.put("author", globalConfig.getAuthor());
    objectMap.put("kotlin", globalConfig.isKotlin());
    objectMap.put("swagger", globalConfig.isSwagger());
    objectMap.put("springdoc", globalConfig.isSpringdoc());
    objectMap.put("date", globalConfig.getCommentDate());
    String schemaName = "";
    if (strategyConfig.isEnableSchema()) {
        schemaName = config.getDataSourceConfig().getSchemaName();
        if (StringUtils.isNotBlank(schemaName)) {
            schemaName = schemaName + ".";
            tableInfo.setConvert(true);
        }
    }
    objectMap.put("schemaName", schemaName);
    objectMap.put("table", tableInfo);
    objectMap.put("entity", tableInfo.getEntityName());
    return objectMap;
}

public @NotNull VelocityEngine init(@NotNull ConfigBuilder configBuilder) {
        Properties p = new Properties();
        p.setProperty("UTF-8", ConstVal.UTF8);
        p.setProperty("resource.default_encoding", ConstVal.UTF8);
        if (configBuilder.getTemplateLoadWay().isFile()) {
            p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            p.setProperty("resource.loader.file.path", "");
            p.setProperty("file.resource.loader.unicode", "true");
        } else {
            p.setProperty("resource.loader", TemplateLoadWay.STRING.getValue());
        }
        return new VelocityEngine(p);
}

} `

Comment From: qmdx

请使用最新版本,目前是支持的用法参考下面方法:

    public List<GenVO> preview(GenDTO dto) {
        List<GenTemplate> genTemplates = genTemplateService.listCheckByIds(dto.getTemplateIds());

        // 初始化数据连接配置
        ConfigBuilder configBuilder = this.buildConfigBuilder(dto);

        // 查询指定表信息
        List<TableInfo> tableInfos = configBuilder.getTableInfoList();
        ApiAssert.fail(CollectionUtils.isEmpty(tableInfos), "未找到指定表信息");
        TableInfo tableInfo = tableInfos.get(0);

        // 初始化模板引擎
        VelocityTemplateEngine templateEngine = new VelocityTemplateEngine().init(configBuilder);
        return genTemplates.stream().map(t -> {
            GenVO vo = new GenVO();
            try {
                Map<String, Object> objectMap = this.getObjectMap(configBuilder, tableInfo);
                vo.setTplName(t.getTplName());
                vo.setTplContent(templateEngine.writer(objectMap, tableInfo.getEntityName(), t.getTplContent()));
                vo.setOutFile(t.getOutFile());
                vo.setRemark(t.getRemark());
            } catch (Exception e) {
                ApiAssert.fail("模板【" + t.getTplName() + "】内容异常");
            }
            return vo;
        }).toList();
    }

Comment From: DuYiFan01

请使用最新版本,目前是支持的用法参考下面方法:

```java public List preview(GenDTO dto) { List genTemplates = genTemplateService.listCheckByIds(dto.getTemplateIds());

    // 初始化数据连接配置
    ConfigBuilder configBuilder = this.buildConfigBuilder(dto);

    // 查询指定表信息
    List<TableInfo> tableInfos = configBuilder.getTableInfoList();
    ApiAssert.fail(CollectionUtils.isEmpty(tableInfos), "未找到指定表信息");
    TableInfo tableInfo = tableInfos.get(0);

    // 初始化模板引擎
    VelocityTemplateEngine templateEngine = new VelocityTemplateEngine().init(configBuilder);
    return genTemplates.stream().map(t -> {
        GenVO vo = new GenVO();
        try {
            Map<String, Object> objectMap = this.getObjectMap(configBuilder, tableInfo);
            vo.setTplName(t.getTplName());
            vo.setTplContent(templateEngine.writer(objectMap, tableInfo.getEntityName(), t.getTplContent()));
            vo.setOutFile(t.getOutFile());
            vo.setRemark(t.getRemark());
        } catch (Exception e) {
            ApiAssert.fail("模板【" + t.getTplName() + "】内容异常");
        }
        return vo;
    }).toList();
}

```

你好,这个代码倒是看懂了,想咨询一下 GenVO GenTemplate没有在MybatisPlus中获取到对应的实体,其中不太理解的方法t.getTplContent(),此方法是否是取到了对应模板的内容,如:service.java.vm中模板实际的内容呢?MybatisPlus是否有支持对应的获取方式,并未找到对应的取得方式