review: 调整代码生成器.

This commit is contained in:
lijiahang
2023-10-30 12:15:03 +08:00
parent d219b7f88a
commit 83a0fb99f1
21 changed files with 559 additions and 333 deletions

View File

@@ -53,7 +53,7 @@ npm run dev
生成通用 controller entity service dao api convert http vue ts sql junit
代码位置
com.orion.ops.framework.mybatis.core.generator.CodeGenerator
com.orion.ops.framework.mybatis.core.generator.CodeGenerators
// 生成的表为 system_role, 业务注释为 '角色', 业务包为 role
Template.create("system_role", "角色", "role")

View File

@@ -0,0 +1,122 @@
package com.orion.ops.framework.mybatis.core.generator;
import com.orion.lang.constant.Const;
import com.orion.lang.utils.ansi.AnsiAppender;
import com.orion.lang.utils.ansi.style.AnsiFont;
import com.orion.lang.utils.ansi.style.color.AnsiForeground;
import com.orion.lang.utils.ext.yml.YmlExt;
import com.orion.ops.framework.mybatis.core.generator.core.CodeGenerator;
import com.orion.ops.framework.mybatis.core.generator.template.Table;
import com.orion.ops.framework.mybatis.core.generator.template.Template;
import java.io.File;
import java.util.concurrent.TimeUnit;
/**
* 代码生成器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2022/4/20 10:33
*/
public class CodeGenerators {
public static void main(String[] args) {
// 输出路径
String outputDir = "D:/MP/";
// 作者
String author = Const.ORION_AUTHOR;
// 模块
String module = "infra";
// 生成的表
Table[] tables = {
// Template.create("preference", "用户偏好", "preference")
// .enableProviderApi()
// .cache("user:preference:{}:{}", "用户偏好 ${type} ${userId}")
// .expire(1, TimeUnit.HOURS)
// .vue("user", "preference")
// .enums("type")
// .names("APP", "HOST")
// // 同 .value(1, 2)
// .values("value", 1, 2)
// // 同 .label("应用", "主机")
// .values("label", "应用", "主机")
// .color("blue", "green")
// .build(),
// Template.create("history_value", "历史归档", "history")
// .enableProviderApi()
// .vue("meta", "history-value")
// .build(),
Template.create("dict_key", "字典配置项", "dict")
.disableOperatorLog()
.cache("dict:keys", "字典配置项")
.expire(1, TimeUnit.DAYS)
.vue("system", "dict-key")
.enums("value_type")
.names("STRING", "INTEGER", "DECIMAL", "BOOLEAN", "COLOR")
.label("字符串", "整数", "小数", "布尔值", "颜色")
.build(),
// Template.create("dict_value", "字典配置值", "dict")
// .cache("dict:value:{}", "字典配置值 ${key}")
// .expire(1, TimeUnit.DAYS)
// .vue("system", "dict-value")
// .enableRowSelection()
// .build(),
};
// jdbc 配置 - 使用配置文件
File yamlFile = new File("orion-ops-launch/src/main/resources/application-dev.yaml");
YmlExt yaml = YmlExt.load(yamlFile);
String url = yaml.getValue("spring.datasource.druid.url");
String username = yaml.getValue("spring.datasource.druid.username");
String password = yaml.getValue("spring.datasource.druid.password");
// 执行
runGenerator(outputDir, author,
tables, module,
url, username, password);
}
/**
* 代码生成
*/
private static void runGenerator(String outputDir,
String author,
Table[] tables,
String module,
String url,
String username,
String password) {
// 执行代码生成
CodeGenerator.builder()
.outputDir(outputDir)
.author(author)
.tables(tables)
.module(module)
.url(url)
.username(username)
.password(password)
.build()
.exec();
// 打印提示信息
printTips();
}
/**
* 打印提示信息
*/
private static void printTips() {
String line = AnsiAppender.create()
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "\n:: 代码生成完毕 ^_^ ::\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 后端代码复制后请先 clean 父工程\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 后端代码需要自行修改缓存逻辑\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 后端代码修改完成后请先执行单元测试检测是否正常\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- vue 代码需要注意同一模块的 router 需要自行合并\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- vue 枚举需要自行更改数据类型\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 菜单 sql 执行完成后 需要在系统菜单页面刷新缓存\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 字典 sql 执行完成后 需要在字典配置项页面刷新缓存\n")
.toString();
System.out.print(line);
}
}

View File

@@ -1,4 +1,4 @@
package com.orion.ops.framework.mybatis.core.generator;
package com.orion.ops.framework.mybatis.core.generator.core;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
@@ -8,24 +8,20 @@ import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.orion.lang.constant.Const;
import com.orion.lang.utils.ansi.AnsiAppender;
import com.orion.lang.utils.ansi.style.AnsiFont;
import com.orion.lang.utils.ansi.style.color.AnsiForeground;
import com.orion.lang.utils.ext.yml.YmlExt;
import com.orion.lang.able.Executable;
import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.mybatis.core.domain.BaseDO;
import com.orion.ops.framework.mybatis.core.generator.engine.VelocityTemplateEngine;
import com.orion.ops.framework.mybatis.core.generator.template.Table;
import com.orion.ops.framework.mybatis.core.generator.template.Template;
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.annotations.Mapper;
import java.io.File;
import java.sql.Types;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -35,94 +31,74 @@ import java.util.stream.Collectors;
* @version 1.0.0
* @since 2022/4/20 10:33
*/
public class CodeGenerator {
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CodeGenerator implements Executable {
public static void main(String[] args) {
// 输出路径
String outputDir = "D:/MP/";
// 作者
String author = Const.ORION_AUTHOR;
// 模块
String module = "infra";
// 生成的表
Table[] tables = {
// Template.create("preference", "用户偏好", "preference")
// .enableProviderApi()
// .cache("user:preference:{}:{}", "用户偏好 ${type} ${userId}")
// .expire(1, TimeUnit.HOURS)
// .vue("user", "preference")
// .enums("type")
// .names("APP", "HOST")
// // .value(1, 2)
// .values("value", 1, 2)
// // .label("应用", "主机")
// .values("label", "应用", "主机")
// .color("blue", "green")
// .build(),
Template.create("history_value", "历史归档", "history")
.enableProviderApi()
.vue("meta", "history-value")
.build(),
Template.create("dict_key", "字典配置项", "dict")
.cache("dict:keys", "字典配置项")
.expire(1, TimeUnit.DAYS)
.vue("system", "dict-key")
.enums("value_type")
.names("STRING", "INTEGER", "DECIMAL", "BOOLEAN", "COLOR")
.label("字符串", "整数", "小数", "布尔值", "颜色")
.build(),
Template.create("dict_value", "字典配置值", "dict")
.cache("dict:value:{}", "字典配置值 ${key}")
.expire(1, TimeUnit.DAYS)
.vue("system", "dict-value")
.enableRowSelection()
.build(),
};
// jdbc 配置 - 使用配置文件
File yamlFile = new File("orion-ops-launch/src/main/resources/application-dev.yaml");
YmlExt yaml = YmlExt.load(yamlFile);
String url = yaml.getValue("spring.datasource.druid.url");
String username = yaml.getValue("spring.datasource.druid.username");
String password = yaml.getValue("spring.datasource.druid.password");
/**
* 输出路径
*/
private String outputDir;
// 执行
runGenerator(outputDir, author,
url, username, password,
tables, module);
}
/**
* 作者
*/
private String author;
/**
* 模块名称
*/
private String module;
/**
*
*/
private Table[] tables;
/**
* 数据库 url
*/
private String url;
/**
* 数据库用户名
*/
private String username;
/**
* 数据库密码
*/
private String password;
/**
* 代码生成
*/
private static void runGenerator(String outputDir,
String author,
String url,
String username,
String password,
Table[] tables,
String module) {
@Override
public void exec() {
Valid.notEmpty(tables, "请先配置需要生成的表");
// 创建引擎
VelocityTemplateEngine engine = getEngine(tables);
VelocityTemplateEngine engine = this.getEngine(tables);
// 获取全局配置
GlobalConfig globalConfig = getGlobalConfig(outputDir, author);
GlobalConfig globalConfig = this.getGlobalConfig(outputDir, author);
// 数据源配置
DataSourceConfig dataSourceConfig = getDataSourceConfig(url, username, password);
DataSourceConfig dataSourceConfig = this.getDataSourceConfig(url, username, password);
// 策略配置
StrategyConfig strategyConfig = getStrategyConfig(tables);
StrategyConfig strategyConfig = this.getStrategyConfig(tables);
// 包名配置
PackageConfig packageConfig = getPackageConfig(module);
PackageConfig packageConfig = this.getPackageConfig(module);
// 模板配置
TemplateConfig templateConfig = getTemplateConfig();
TemplateConfig templateConfig = this.getTemplateConfig();
// 注入配置
InjectionConfig injectionConfig = getInjectionConfig();
InjectionConfig injectionConfig = this.getInjectionConfig();
// 整合配置
AutoGenerator ag = new AutoGenerator(dataSourceConfig)
@@ -139,9 +115,6 @@ public class CodeGenerator {
// 执行
ag.execute(engine);
// 打印提示信息
printTips();
}
/**
@@ -150,8 +123,8 @@ public class CodeGenerator {
* @param tables
* @return 渲染引擎
*/
private static VelocityTemplateEngine getEngine(Table[] tables) {
return new VelocityTemplateEngine(tables);
private CodeGeneratorEngine getEngine(Table[] tables) {
return new CodeGeneratorEngine(tables);
}
/**
@@ -161,7 +134,7 @@ public class CodeGenerator {
* @param author 作者
* @return config
*/
private static GlobalConfig getGlobalConfig(String outputDir, String author) {
private GlobalConfig getGlobalConfig(String outputDir, String author) {
return new GlobalConfig.Builder()
// 设置作者
.author(author)
@@ -185,7 +158,7 @@ public class CodeGenerator {
* @param password password
* @return 数据源配置
*/
private static DataSourceConfig getDataSourceConfig(String url, String username, String password) {
private DataSourceConfig getDataSourceConfig(String url, String username, String password) {
return new DataSourceConfig.Builder(url, username, password)
// 转换器
.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
@@ -209,7 +182,7 @@ public class CodeGenerator {
* @param tables 生成的表名
* @return 策略配置
*/
private static StrategyConfig getStrategyConfig(Table[] tables) {
private StrategyConfig getStrategyConfig(Table[] tables) {
String[] tableNames = Arrays.stream(tables)
.map(Table::getTableName)
.toArray(String[]::new);
@@ -281,7 +254,7 @@ public class CodeGenerator {
* @param module 模块
* @return 包名配置
*/
private static PackageConfig getPackageConfig(String module) {
private PackageConfig getPackageConfig(String module) {
return new PackageConfig.Builder()
// 声明父包
.parent("com.orion.ops.module")
@@ -308,7 +281,7 @@ public class CodeGenerator {
*
* @return 模板配置
*/
private static TemplateConfig getTemplateConfig() {
private TemplateConfig getTemplateConfig() {
return new TemplateConfig.Builder()
.controller("/templates/orion-server-module-controller.java.vm")
.entity("/templates/orion-server-module-entity-do.java.vm")
@@ -324,7 +297,7 @@ public class CodeGenerator {
*
* @return 注入配置
*/
private static InjectionConfig getInjectionConfig() {
private InjectionConfig getInjectionConfig() {
String[][] customFileDefineArr = new String[][]{
// -------------------- 后端 - module --------------------
// http 文件
@@ -395,7 +368,9 @@ public class CodeGenerator {
// card.fields.ts 文件
new String[]{"/templates/orion-vue-views-types-card.fields.ts.vm", "card.fields.ts", "vue/views/${module}/${feature}/types"},
// menu.sql 文件
new String[]{"/templates/orion-sql-menu.sql.vm", "${feature}-menu.sql", "sql"},
new String[]{"/templates/orion-sql-menu.sql.vm", "${tableName}-menu.sql", "sql"},
// dict.sql 文件
new String[]{"/templates/orion-sql-dict.sql.vm", "${tableName}-dict.sql", "sql"},
};
// 构建文件
@@ -420,21 +395,4 @@ public class CodeGenerator {
.build();
}
/**
* 打印提示信息
*/
private static void printTips() {
String line = AnsiAppender.create()
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "\n:: 代码生成完毕 ^_^ ::\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 后端代码复制后请先 clean 父工程\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 后端代码需要自行修改缓存逻辑\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 后端代码修改完成后请先执行单元测试检测是否正常\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- vue 代码需要注意同一模块的 router 需要自行合并\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- vue 枚举需要自行更改数据类型\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 菜单 sql 执行完成后 需要在系统菜单页面刷新缓存\n")
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "- 字典 sql 执行完成后 需要在字典配置项页面刷新缓存\n")
.toString();
System.out.print(line);
}
}

View File

@@ -1,28 +1,10 @@
/*
* Copyright (c) 2011-2022, baomidou (jobob@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.orion.ops.framework.mybatis.core.generator.engine;
package com.orion.ops.framework.mybatis.core.generator.core;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.orion.lang.define.collect.MultiLinkedHashMap;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.VariableStyles;
@@ -33,16 +15,9 @@ import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.OrionOpsProConst;
import com.orion.ops.framework.mybatis.core.generator.template.Table;
import com.orion.ops.framework.mybatis.core.generator.template.VueEnum;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -50,68 +25,25 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* 代码生成器 Velocity 引擎
* 代码生成器引擎
*
* @author Jiahang Li
* @version 1.0.0
* @since 2022/4/20 10:33
* @since 2023/10/30 11:20
*/
public class VelocityTemplateEngine extends AbstractTemplateEngine {
public class CodeGeneratorEngine extends VelocityTemplateEngine {
private final Map<String, Table> tables;
private VelocityEngine velocityEngine;
public VelocityTemplateEngine(Table[] tables) {
public CodeGeneratorEngine(Table[] tables) {
this.tables = Arrays.stream(tables)
.collect(Collectors.toMap(Table::getTableName, Function.identity()));
}
{
try {
Class.forName("org.apache.velocity.util.DuckType");
} catch (ClassNotFoundException e) {
LOGGER.warn("Velocity 1.x is outdated, please upgrade to 2.x or later.");
}
}
@Override
@NotNull
public VelocityTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
if (velocityEngine == null) {
Properties p = new Properties();
p.setProperty(ConstVal.VM_LOAD_PATH_KEY, ConstVal.VM_LOAD_PATH_VALUE);
p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, StringPool.EMPTY);
p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
p.setProperty("file.resource.loader.unicode", StringPool.TRUE);
this.velocityEngine = new VelocityEngine(p);
}
return this;
}
@Override
public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
Template template = velocityEngine.getTemplate(templatePath, ConstVal.UTF8);
try (FileOutputStream fos = new FileOutputStream(outputFile);
OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
BufferedWriter writer = new BufferedWriter(ow)) {
template.merge(new VelocityContext(objectMap), writer);
}
LOGGER.debug("模板: " + templatePath + "; 文件: " + outputFile);
}
@Override
@NotNull
public String templateFilePath(@NotNull String filePath) {
final String dotVm = ".vm";
return filePath.endsWith(dotVm) ? filePath : filePath + dotVm;
}
@Override
protected void outputCustomFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// 创建自定义文件副本文件
customFiles = this.createCustomFilesBackup(customFiles, tableInfo);
// 过滤文件
customFiles = new CustomFileFilter(tables.get(tableInfo.getName()), customFiles).doFilter();
// 添加表元数据
this.addTableMeta(tableInfo, objectMap);
// 替换自定义包名
@@ -122,52 +54,8 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
this.generatorServerFile(customFiles, tableInfo, objectMap);
// 生成前端文件
this.generatorVueFile(customFiles, tableInfo, objectMap);
}
/**
* 创建自定义文件副本对象
* <p>
* - 根据类型进行移除不需要生成的模板
*
* @param originCustomerFile originCustomerFile
* @param tableInfo tableInfo
* @return backup
*/
private List<CustomFile> createCustomFilesBackup(@NotNull List<CustomFile> originCustomerFile,
@NotNull TableInfo tableInfo) {
// 生成文件副本
List<CustomFile> files = originCustomerFile.stream().map(s ->
new CustomFile.Builder()
.enableFileOverride()
.templatePath(s.getTemplatePath())
.filePath(s.getFilePath())
.fileName(s.getFileName())
.packageName(s.getPackageName())
.build())
.collect(Collectors.toList());
// 获取 table
Table table = tables.get(tableInfo.getName());
// 不生成对外 api 文件
if (!table.isEnableProviderApi()) {
files.removeIf(file -> this.isServerProviderFile(file.getTemplatePath()));
// 不生成对外 api 单元测试文件
if (table.isEnableUnitTest()) {
files.removeIf(file -> this.isServerProviderTestFile(file.getTemplatePath()));
}
}
// 不生成单元测试文件
if (!table.isEnableUnitTest()) {
files.removeIf(file -> this.isServerUnitTestFile(file.getTemplatePath()));
}
// 不生成缓存文件
if (!table.isEnableCache()) {
files.removeIf(file -> this.isServerCacheFile(file.getTemplatePath()));
}
// 不生成 vue 文件
if (!table.isEnableVue()) {
files.removeIf(file -> this.isVueFile(file.getTemplatePath()));
}
return files;
// 生成 sql 文件
this.generatorSqlFile(customFiles, tableInfo, objectMap);
}
/**
@@ -184,11 +72,9 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
// 替换业务注释
tableInfo.setComment(tables.get(tableInfo.getName()).getComment());
Table table = tables.get(tableInfo.getName());
// 缓存元数据
Map<String, Object> cacheMeta = this.pickTableMeta(table,
"enableCache", "cacheKey", "cacheDesc",
"cacheExpired", "cacheExpireTime", "cacheExpireUnit");
objectMap.put("cacheMeta", cacheMeta);
// 元数据
Map<String, Object> meta = BeanMap.create(table);
objectMap.put("meta", meta);
// 实体名称
String domainName = tableInfo.getEntityName();
String mappingHyphen = objectMap.get("controllerMappingHyphen").toString();
@@ -282,7 +168,7 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
private void generatorServerFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// 过滤文件
customFiles = customFiles.stream()
.filter(s -> this.isServerFile(s.getTemplatePath()))
.filter(s -> CustomFileFilter.isServerFile(s.getTemplatePath()))
.collect(Collectors.toList());
// 生成文件
@@ -319,11 +205,11 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
}
// 过滤文件
customFiles = customFiles.stream()
.filter(s -> this.isVueFile(s.getTemplatePath()))
.filter(s -> CustomFileFilter.isVueFile(s.getTemplatePath()))
.collect(Collectors.toList());
// 设置前端元数据
Table table = tables.get(tableInfo.getName());
Map<String, Object> vueMeta = this.pickTableMeta(table, "module", "feature", "enableDrawerForm", "enableRowSelection", "enableCardView");
Map<String, Object> vueMeta = BeanMap.create(table);
// 模块名称实体
vueMeta.put("moduleEntity", VariableStyles.SPINE.toBigHump(table.getModule()));
// 模块名称实体
@@ -352,80 +238,29 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
}
/**
* 是否为后端文件
* 生成 sql 文件
*
* @param templatePath templatePath
* @return 是否为后端文件
* @param customFiles customFiles
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private boolean isServerFile(String templatePath) {
return templatePath.contains("orion-server");
}
/**
* 是否为后端 provider 文件
*
* @param templatePath templatePath
* @return 是否为后端 provider 文件
*/
private boolean isServerProviderFile(String templatePath) {
return templatePath.contains("orion-server-provider");
}
/**
* 是否为后端 provider 单元测试文件
*
* @param templatePath templatePath
* @return 是否为后端 provider 单元测试文件
*/
private boolean isServerProviderTestFile(String templatePath) {
return templatePath.contains("orion-server-test-api");
}
/**
* 是否为后端单元测试文件
*
* @param templatePath templatePath
* @return 是否为后端单元测试文件
*/
private boolean isServerUnitTestFile(String templatePath) {
return templatePath.contains("orion-server-test");
}
/**
* 是否为后端缓存文件
*
* @param templatePath templatePath
* @return 是否为后端缓存文件
*/
private boolean isServerCacheFile(String templatePath) {
return templatePath.contains("orion-server-module-cache");
}
/**
* 是否为 vue 文件
*
* @param templatePath templatePath
* @return 是否为 vue 文件
*/
private boolean isVueFile(String templatePath) {
return templatePath.contains("orion-vue-") ||
templatePath.contains("orion-sql-menu.sql");
}
/**
* 获取表元数据
*
* @param table table
* @param keys keys
* @return meta
*/
private Map<String, Object> pickTableMeta(Table table, String... keys) {
BeanMap beanMap = BeanMap.create(table);
Map<String, Object> tableMeta = new HashMap<>();
for (String key : keys) {
tableMeta.put(key, beanMap.get(key));
}
return tableMeta;
private void generatorSqlFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// 过滤文件
customFiles = customFiles.stream()
.filter(s -> CustomFileFilter.isDataSqlFile(s.getTemplatePath()))
.collect(Collectors.toList());
// 设置元数据
Table table = tables.get(tableInfo.getName());
Map<String, Object> meta = BeanMap.create(table);
// 生成文件
customFiles.forEach(file -> {
// 文件路径
String filePath = getConfigBuilder().getGlobalConfig().getOutputDir()
+ "/" + Strings.format(file.getPackageName(), meta)
+ "/" + Strings.format(file.getFileName(), meta);
// 渲染文件
this.outputFile(Files1.newFile(filePath), objectMap, file.getTemplatePath(), file.isFileOverride());
});
}
/**
@@ -493,7 +328,6 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
} else {
return null;
}
}
}

View File

@@ -0,0 +1,183 @@
package com.orion.ops.framework.mybatis.core.generator.core;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.orion.ops.framework.mybatis.core.generator.template.Table;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义文件过滤器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/30 11:08
*/
public class CustomFileFilter {
/**
* 表
*/
private final Table table;
/**
* 原始文件
*/
private final List<CustomFile> originCustomerFile;
public CustomFileFilter(Table table, List<CustomFile> originCustomerFile) {
this.table = table;
this.originCustomerFile = originCustomerFile;
}
/**
* 执行过滤
*
* @return clone filter files
*/
public List<CustomFile> doFilter() {
// 生成文件副本
List<CustomFile> files = originCustomerFile.stream().map(s ->
new CustomFile.Builder()
.enableFileOverride()
.templatePath(s.getTemplatePath())
.filePath(s.getFilePath())
.fileName(s.getFileName())
.packageName(s.getPackageName())
.build())
.collect(Collectors.toList());
// 不生成对外 api 文件
if (!table.isEnableProviderApi()) {
files.removeIf(file -> isServerProviderFile(file.getTemplatePath()));
// 不生成对外 api 单元测试文件
if (table.isEnableUnitTest()) {
files.removeIf(file -> isServerProviderTestFile(file.getTemplatePath()));
}
}
// 不生成单元测试文件
if (!table.isEnableUnitTest()) {
files.removeIf(file -> isServerUnitTestFile(file.getTemplatePath()));
}
// 不生成缓存文件
if (!table.isEnableCache()) {
files.removeIf(file -> isServerCacheFile(file.getTemplatePath()));
}
// 不生成导出文件
if (!table.isEnableExport()) {
files.removeIf(file -> isExportFile(file.getTemplatePath()));
}
// 不生成操作日志文件
if (!table.isEnableOperatorLog()) {
files.removeIf(file -> isOperatorLogFile(file.getTemplatePath()));
}
// 不生成 vue 文件
if (!table.isEnableVue()) {
files.removeIf(file -> isVueFile(file.getTemplatePath()));
// 不生成菜单 sql 文件
files.removeIf(file -> isMenuDataFile(file.getTemplatePath()));
}
return files;
}
/**
* 是否为后端文件
*
* @param templatePath templatePath
* @return 是否为后端文件
*/
public static boolean isServerFile(String templatePath) {
return templatePath.contains("orion-server");
}
/**
* 是否为后端 provider 文件
*
* @param templatePath templatePath
* @return 是否为后端 provider 文件
*/
public static boolean isServerProviderFile(String templatePath) {
return templatePath.contains("orion-server-provider");
}
/**
* 是否为后端 provider 单元测试文件
*
* @param templatePath templatePath
* @return 是否为后端 provider 单元测试文件
*/
public static boolean isServerProviderTestFile(String templatePath) {
return templatePath.contains("orion-server-test-api");
}
/**
* 是否为后端单元测试文件
*
* @param templatePath templatePath
* @return 是否为后端单元测试文件
*/
public static boolean isServerUnitTestFile(String templatePath) {
return templatePath.contains("orion-server-test");
}
/**
* 是否为后端缓存文件
*
* @param templatePath templatePath
* @return 是否为后端缓存文件
*/
public static boolean isServerCacheFile(String templatePath) {
return templatePath.contains("orion-server-module-cache");
}
/**
* 是否为导出文件
*
* @param templatePath templatePath
* @return 是否为导出文件
*/
public static boolean isExportFile(String templatePath) {
return templatePath.contains("orion-server-module-entity-export");
}
/**
* 是否为操作日志文件
*
* @param templatePath templatePath
* @return 是否为操作日志文件
*/
public static boolean isOperatorLogFile(String templatePath) {
return templatePath.contains("orion-server-module-operator-key-define");
}
/**
* 是否为菜单 sql 文件
*
* @param templatePath templatePath
* @return 是否为菜单 sql 文件
*/
public static boolean isMenuDataFile(String templatePath) {
return templatePath.contains("orion-sql-menu");
}
/**
* 是否为 sql ddl 文件
*
* @param templatePath templatePath
* @return 是否为数据库数据文件
*/
public static boolean isDataSqlFile(String templatePath) {
return templatePath.contains("orion-sql-menu") ||
templatePath.contains("orion-sql-dict");
}
/**
* 是否为 vue 文件
*
* @param templatePath templatePath
* @return 是否为 vue 文件
*/
public static boolean isVueFile(String templatePath) {
return templatePath.contains("orion-vue-");
}
}

View File

@@ -1,4 +1,4 @@
package com.orion.ops.framework.mybatis.core.generator.engine;
package com.orion.ops.framework.mybatis.core.generator.core;
import com.orion.lang.define.collect.MultiLinkedHashMap;
import lombok.AllArgsConstructor;

View File

@@ -0,0 +1,72 @@
package com.orion.ops.framework.mybatis.core.generator.core;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.Map;
import java.util.Properties;
/**
* 代码生成器 Velocity 引擎
*
* @author Jiahang Li
* @version 1.0.0
* @since 2022/4/20 10:33
*/
public class VelocityTemplateEngine extends AbstractTemplateEngine {
private VelocityEngine velocityEngine;
{
try {
Class.forName("org.apache.velocity.util.DuckType");
} catch (ClassNotFoundException e) {
LOGGER.warn("Velocity 1.x is outdated, please upgrade to 2.x or later.");
}
}
@Override
@NotNull
public VelocityTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
if (velocityEngine == null) {
Properties p = new Properties();
p.setProperty(ConstVal.VM_LOAD_PATH_KEY, ConstVal.VM_LOAD_PATH_VALUE);
p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, StringPool.EMPTY);
p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
p.setProperty("file.resource.loader.unicode", StringPool.TRUE);
this.velocityEngine = new VelocityEngine(p);
}
return this;
}
@Override
public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
Template template = velocityEngine.getTemplate(templatePath, ConstVal.UTF8);
try (FileOutputStream fos = new FileOutputStream(outputFile);
OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
BufferedWriter writer = new BufferedWriter(ow)) {
template.merge(new VelocityContext(objectMap), writer);
}
LOGGER.debug("模板: " + templatePath + "; 文件: " + outputFile);
}
@Override
@NotNull
public String templateFilePath(@NotNull String filePath) {
final String dotVm = ".vm";
return filePath.endsWith(dotVm) ? filePath : filePath + dotVm;
}
}

View File

@@ -72,7 +72,6 @@ public class ServerTemplate extends Template {
return this;
}
// fixme
/**
* 生成导出
*
@@ -93,14 +92,13 @@ public class ServerTemplate extends Template {
return this;
}
// fixme
/**
* 不生成操作日志
*
* @return this
*/
public ServerTemplate disableOperatorLog() {
table.enableUnitTest = false;
table.enableOperatorLog = false;
return this;
}

View File

@@ -18,11 +18,11 @@ import java.util.concurrent.TimeUnit;
public interface ${type}CacheKeyDefine {
CacheKeyDefine $typeConst = new CacheKeyBuilder()
.key("$cacheMeta.cacheKey")
.desc("$cacheMeta.cacheDesc")
.key("$meta.cacheKey")
.desc("$meta.cacheDesc")
.type(${type}CacheDTO.class)
#if($cacheMeta.cacheExpired)
.timeout($cacheMeta.cacheExpireTime, TimeUnit.$cacheMeta.cacheExpireUnit.name())
#if($meta.cacheExpired)
.timeout($meta.cacheExpireTime, TimeUnit.$meta.cacheExpireUnit.name())
#end
.build();

View File

@@ -68,6 +68,7 @@ Authorization: {{token}}
${httpComment} ${apiComment.batchDelete}
DELETE {{baseUrl}}/${package.ModuleName}/${typeHyphen}/batch-delete?idList=1,2,3
Authorization: {{token}}
#if($meta.enableExport)
${httpComment} ${apiComment.export}
@@ -80,6 +81,6 @@ Authorization: {{token}}
"${field.propertyName}": ""#if($foreach.hasNext),#end
#end
}
#end
${httpComment}

View File

@@ -1,7 +1,9 @@
package ${package.Controller};
import com.orion.lang.define.wrapper.DataGrid;
#if($meta.enableOperatorLog)
import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
#end
import com.orion.ops.framework.common.validator.group.Page;
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
@@ -49,7 +51,9 @@ public class ${table.controllerName} {
@Resource
private ${type}Service ${typeLower}Service;
#if($meta.enableOperatorLog)
@OperatorLog(${type}OperatorType.CREATE)
#end
@PostMapping("/create")
@Operation(summary = "${apiComment.create}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:create')")
@@ -57,7 +61,9 @@ public class ${table.controllerName} {
return ${typeLower}Service.create${type}(request);
}
#if($meta.enableOperatorLog)
@OperatorLog(${type}OperatorType.UPDATE)
#end
@PutMapping("/update")
@Operation(summary = "${apiComment.updateById}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:update')")
@@ -99,7 +105,9 @@ public class ${table.controllerName} {
return ${typeLower}Service.get${type}Page(request);
}
#if($meta.enableOperatorLog)
@OperatorLog(${type}OperatorType.DELETE)
#end
@DeleteMapping("/delete")
@Operation(summary = "${apiComment.deleteById}")
@Parameter(name = "id", description = "id", required = true)
@@ -108,7 +116,9 @@ public class ${table.controllerName} {
return ${typeLower}Service.delete${type}ById(id);
}
#if($meta.enableOperatorLog)
@OperatorLog(${type}OperatorType.DELETE)
#end
@DeleteMapping("/batch-delete")
@Operation(summary = "${apiComment.batchDelete}")
@Parameter(name = "idList", description = "idList", required = true)
@@ -116,8 +126,11 @@ public class ${table.controllerName} {
public Integer batchDelete${type}(@RequestParam("idList") List<Long> idList) {
return ${typeLower}Service.delete${type}ByIdList(idList);
}
#if($meta.enableExport)
#if($meta.enableOperatorLog)
@OperatorLog(${type}OperatorType.EXPORT)
#end
@PostMapping("/export")
@Operation(summary = "${apiComment.export}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:export')")
@@ -125,6 +138,7 @@ public class ${table.controllerName} {
HttpServletResponse response) throws IOException {
${typeLower}Service.export${type}(request, response);
}
#end
}

View File

@@ -28,12 +28,14 @@ public interface ${type}Convert {
${type}DO to(${type}QueryRequest request);
${type}VO to(${type}DO domain);
#if($meta.enableExport)
${type}Export toExport(${type}DO domain);
#end
List<${type}VO> to(List<${type}DO> list);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
${type}VO to(${type}CacheDTO cache);
${type}CacheDTO toCache(${type}DO domain);

View File

@@ -21,8 +21,10 @@ public class ${type}OperatorType extends InitializingOperatorTypes {
public static final String UPDATE = "${typeHyphen}:update";
public static final String DELETE = "${typeHyphen}:delete";
#if($meta.enableExport)
public static final String EXPORT = "${typeHyphen}:export";
#end
@Override
public OperatorType[] types() {
@@ -30,7 +32,9 @@ public class ${type}OperatorType extends InitializingOperatorTypes {
new OperatorType(L, CREATE, "创建$!{table.comment}"),
new OperatorType(M, UPDATE, "更新$!{table.comment}"),
new OperatorType(H, DELETE, "删除$!{table.comment}"),
#if($meta.enableExport)
new OperatorType(M, EXPORT, "导出$!{table.comment}"),
#end
};
}

View File

@@ -5,14 +5,16 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.collect.Lists;
#if($meta.enableExport)
import com.orion.office.excel.writer.exporting.ExcelExport;
#if($cacheMeta.enableCache)
#end
#if($meta.enableCache)
import com.orion.ops.framework.common.constant.Const;
#end
import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.utils.FileNames;
import com.orion.ops.framework.common.utils.Valid;
#if($cacheMeta.enableCache)
#if($meta.enableCache)
import com.orion.ops.framework.redis.core.utils.RedisMaps;
#end
#foreach($pkg in ${customModuleFilePackages})
@@ -57,7 +59,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
int effect = ${typeLower}DAO.insert(record);
Long id = record.getId();
log.info("${type}Service-create${type} id: {}, effect: {}", id, effect);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// 删除缓存
RedisMaps.delete(${type}CacheKeyDefine.${typeConst});
#end
@@ -78,7 +80,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
// 更新
int effect = ${typeLower}DAO.updateById(updateRecord);
log.info("${type}Service-update${type}ById effect: {}", effect);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// 删除缓存
RedisMaps.delete(${type}CacheKeyDefine.${typeConst});
#end
@@ -95,7 +97,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
// 更新
int effect = ${typeLower}DAO.update(updateRecord, wrapper);
log.info("${type}Service.update${type} effect: {}", effect);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// 删除缓存
RedisMaps.delete(${type}CacheKeyDefine.${typeConst});
#end
@@ -130,7 +132,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
return ${typeLower}DAO.of(wrapper).list(${type}Convert.MAPPER::to);
}
#if($cacheMeta.enableCache)
#if($meta.enableCache)
@Override
public List<${type}VO> get${type}ListByCache() {
// 查询缓存
@@ -183,7 +185,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
// 删除
int effect = ${typeLower}DAO.deleteById(id);
log.info("${type}Service-delete${type}ById id: {}, effect: {}", id, effect);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// 删除缓存
RedisMaps.delete(${type}CacheKeyDefine.${typeConst}, id);
#end
@@ -195,7 +197,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
log.info("${type}Service-delete${type}ByIdList idList: {}", idList);
int effect = ${typeLower}DAO.deleteBatchIds(idList);
log.info("${type}Service-delete${type}ByIdList effect: {}", effect);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// 删除缓存
RedisMaps.delete(${type}CacheKeyDefine.${typeConst}, idList);
#end
@@ -210,12 +212,13 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
// 删除
int effect = ${typeLower}DAO.delete(wrapper);
log.info("${type}Service.delete${type} effect: {}", effect);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// 删除缓存
RedisMaps.delete(${type}CacheKeyDefine.${typeConst});
#end
return effect;
}
#if($meta.enableExport)
@Override
public void export${type}(${type}QueryRequest request, HttpServletResponse response) throws IOException {
@@ -234,6 +237,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
// 传输
Servlets.transfer(response, out.toByteArray(), FileNames.exportName(${type}Export.TITLE));
}
#end
/**
* 检查对象是否存在

View File

@@ -67,7 +67,7 @@ public interface ${table.serviceName} {
*/
List<${type}VO> get${type}List(${type}QueryRequest request);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
/**
* ${apiComment.queryListByCache}
*
@@ -115,6 +115,7 @@ public interface ${table.serviceName} {
* @return effect
*/
Integer delete${type}(${type}QueryRequest request);
#if($meta.enableExport)
/**
* ${apiComment.export}
@@ -124,5 +125,6 @@ public interface ${table.serviceName} {
* @throws IOException IOException
*/
void export${type}(${type}QueryRequest request, HttpServletResponse response) throws IOException;
#end
}

View File

@@ -106,7 +106,7 @@ public class ${type}ApiImpl implements ${type}Api {
return ${typeLower}DAO.of(wrapper).list(${type}ProviderConvert.MAPPER::to);
}
#if($cacheMeta.enableCache)
#if($meta.enableCache)
@Override
public List<${type}DTO> get${type}ListByCache() {
return ${typeLower}Service.get${type}ListByCache()

View File

@@ -64,7 +64,7 @@ public interface ${type}Api {
*/
List<${type}DTO> get${type}List(${type}QueryDTO dto);
#if($cacheMeta.enableCache)
#if($meta.enableCache)
/**
* ${apiComment.queryListByCache}
*

View File

@@ -110,7 +110,7 @@ public class ${type}ApiImplTests extends BaseUnitTest {
Integer effect = ${typeLower}Api.delete${type}(dto);
assertEquals(effect, 0);
}
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// -------------------- cache --------------------

View File

@@ -121,7 +121,7 @@ public class ${type}ServiceImplTests extends BaseUnitTest {
Integer effect = ${typeLower}Service.delete${type}(query);
assertEquals(effect, 0);
}
#if($cacheMeta.enableCache)
#if($meta.enableCache)
// -------------------- cache --------------------

View File

@@ -0,0 +1,30 @@
-- 执行完成后 需要在菜单页面刷新缓存
-- 父菜单
INSERT INTO system_menu
(parent_id, name, type, sort, visible, status, cache, component)
VALUES
(0, '${table.comment}管理', 1, 10, 1, 1, 1, '$vue.moduleEntityFirstLower');
-- 设置临时父菜单id
SELECT @TMP_PARENT_ID:=LAST_INSERT_ID();
-- 子菜单
INSERT INTO system_menu
(parent_id, name, type, sort, visible, status, cache, component)
VALUES
(@TMP_PARENT_ID, '$table.comment', 2, 10, 1, 1, 1, '$vue.moduleEntityFirstLower$vue.featureEntity');
-- 设置临时子菜单id
SELECT @TMP_SUB_ID:=LAST_INSERT_ID();
-- 功能
INSERT INTO system_menu
(parent_id, name, permission, type, sort)
VALUES
(@TMP_SUB_ID, '查询$table.comment', '${package.ModuleName}:${typeHyphen}:query', 3, 10),
(@TMP_SUB_ID, '创建$table.comment', '${package.ModuleName}:${typeHyphen}:create', 3, 20),
(@TMP_SUB_ID, '修改$table.comment', '${package.ModuleName}:${typeHyphen}:update', 3, 30),
(@TMP_SUB_ID, '删除$table.comment', '${package.ModuleName}:${typeHyphen}:delete', 3, 40),
(@TMP_SUB_ID, '导出$table.comment', '${package.ModuleName}:${typeHyphen}:export', 3, 50),
(@TMP_SUB_ID, '导入$table.comment', '${package.ModuleName}:${typeHyphen}:import', 3, 60);

View File

@@ -133,6 +133,7 @@ export function batchDelete${vue.featureEntity}(idList: Array<number>) {
}
});
}
#if($meta.enableExport)
/**
* $apiComment.export
@@ -140,3 +141,4 @@ export function batchDelete${vue.featureEntity}(idList: Array<number>) {
export function export${vue.featureEntity}(request: ${vue.featureEntity}QueryRequest) {
return axios.post('/${package.ModuleName}/${typeHyphen}/export', request);
}
#end