update 重构代码生成工具链,复用代码模板以提升代码生成性能

This commit is contained in:
疯狂的狮子Li
2026-04-01 10:07:21 +08:00
parent 87647231d5
commit 65c4a7a964
14 changed files with 592 additions and 292 deletions

View File

@@ -1,66 +0,0 @@
package org.dromara.gen.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 代码生成相关配置
*
* @author ruoyi
*/
@Component
@ConfigurationProperties(prefix = "gen")
public class GenConfig {
/**
* 作者
*/
public static String author;
/**
* 生成包路径
*/
public static String packageName;
/**
* 自动去除表前缀默认是false
*/
public static boolean autoRemovePre;
/**
* 表前缀(类名不会包含表前缀)
*/
public static String tablePrefix;
public static String getAuthor() {
return author;
}
public void setAuthor(String author) {
GenConfig.author = author;
}
public static String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
GenConfig.packageName = packageName;
}
public static boolean getAutoRemovePre() {
return autoRemovePre;
}
public void setAutoRemovePre(boolean autoRemovePre) {
GenConfig.autoRemovePre = autoRemovePre;
}
public static String getTablePrefix() {
return tablePrefix;
}
public void setTablePrefix(String tablePrefix) {
GenConfig.tablePrefix = tablePrefix;
}
}

View File

@@ -25,6 +25,9 @@ import java.util.Map;
@Component
public class MyBatisDataSourceMonitor implements DataSourceMonitor {
/**
* 初始化 anyline 与动态数据源联动所需的元数据解析策略。
*/
public MyBatisDataSourceMonitor() {
// 调整执行模式为自定义
ConfigTable.KEEP_ADAPTER = 2;
@@ -72,6 +75,8 @@ public class MyBatisDataSourceMonitor implements DataSourceMonitor {
/**
* 数据源唯一标识 如果不实现则默认feature
*
* @param runtime 数据运行时上下文
* @param datasource 数据源
* @return String 返回null由上层自动提取
*/
@@ -90,6 +95,7 @@ public class MyBatisDataSourceMonitor implements DataSourceMonitor {
* ConfigTable.KEEP_ADAPTER=2 : 根据当前接口判断是否保持同一个数据源绑定同一个adapter<br/>
* DynamicRoutingDataSource类型的返回false,因为同一个DynamicRoutingDataSource可能对应多类数据库, 如果项目中只有一种数据库 应该直接返回true
*
* @param runtime 数据运行时上下文
* @param datasource 数据源
* @return boolean
*/

View File

@@ -0,0 +1,47 @@
package org.dromara.gen.config.properties;
import cn.hutool.extra.template.TemplateConfig;
import lombok.Data;
import org.dromara.common.core.factory.YmlPropertySourceFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
/**
* 代码生成配置属性
*
* @author 秋辞未寒
*/
@Data
@Component
@ConfigurationProperties(prefix = "gen")
public class GenProperties {
/**
* 作者
*/
private String author;
/**
* 生成包路径
*/
private String packageName;
/**
* 自动去除表前缀默认是false
*/
private boolean autoRemovePre = false;
/**
* 表前缀(类名不会包含表前缀)
*/
private String tablePrefix;
/**
* 模板配置
*/
private TemplateConfig templateConfig = new TemplateConfig(StandardCharsets.UTF_8, null, TemplateConfig.ResourceMode.CLASSPATH);
}

View File

@@ -1,5 +1,9 @@
package org.dromara.gen.constant;
import cn.hutool.core.collection.CollUtil;
import java.util.Set;
/**
* 代码生成通用常量
*
@@ -69,25 +73,25 @@ public interface GenConstants {
* BO对象 不需要添加字段
*/
String[] COLUMNNAME_NOT_ADD = {"create_dept", "create_by", "create_time", "del_flag", "update_by",
"update_time", "version", "tenant_id"};
"update_time", "version"};
/**
* BO对象 不需要编辑字段
*/
String[] COLUMNNAME_NOT_EDIT = {"create_dept", "create_by", "create_time", "del_flag", "update_by",
"update_time", "version", "tenant_id"};
"update_time", "version"};
/**
* VO对象 不需要返回字段
*/
String[] COLUMNNAME_NOT_LIST = {"create_dept", "create_by", "create_time", "del_flag", "update_by",
"update_time", "version", "tenant_id"};
"update_time", "version"};
/**
* BO对象 不需要查询字段
*/
String[] COLUMNNAME_NOT_QUERY = {"id", "create_dept", "create_by", "create_time", "del_flag", "update_by",
"update_time", "remark", "version", "tenant_id"};
"update_time", "remark", "version"};
/**
* Entity基类字段
@@ -178,14 +182,57 @@ public interface GenConstants {
* 相等查询
*/
String QUERY_EQ = "EQ";
/**
* 范围查询
*/
String QUERY_BETWEEN = "BETWEEN";
/**
* 需要
* 必填标识,对应前端表单规则中的必填字段配置。
*/
String REQUIRE = "1";
// 后端源码模板
String JAVA_DOMAIN_TEMPLATE_PATH = "vm/java/domain.java.vm";
String JAVA_VO_TEMPLATE_PATH = "vm/java/vo.java.vm";
String JAVA_BO_TEMPLATE_PATH = "vm/java/bo.java.vm";
String JAVA_MAPPER_TEMPLATE_PATH = "vm/java/mapper.java.vm";
String JAVA_SERVICE_TEMPLATE_PATH = "vm/java/service.java.vm";
String JAVA_SERVICE_IMPL_TEMPLATE_PATH = "vm/java/serviceImpl.java.vm";
String JAVA_CONTROLLER_TEMPLATE_PATH = "vm/java/controller.java.vm";
// MyBatis MapperXML 模板
String XML_MAPPER_TEMPLATE_PATH = "vm/xml/mapper.xml.vm";
// 前端接口源码模板
String TS_API_TEMPLATE_PATH = "vm/ts/api.ts.vm";
String TS_TYPES_TEMPLATE_PATH = "vm/ts/types.ts.vm";
// 前端页面源码模板
String VUE_INDEX_TEMPLATE_PATH = "vm/vue/index.vue.vm";
String VUE_INDEX_TREE_TEMPLATE_PATH = "vm/vue/index-tree.vue.vm";
// 数据库SQL模板
String SQL_ORACLE_TEMPLATE_PATH = "vm/sql/oracle.sql.vm";
String SQL_POSTGRES_TEMPLATE_PATH = "vm/sql/postgres.sql.vm";
String SQL_SQLSERVER_TEMPLATE_PATH = "vm/sql/sqlserver.sql.vm";
String SQL_MYSQL_TEMPLATE_PATH = "vm/sql/mysql.sql.vm";
/**
* 所有模板路径集合
*/
Set<String> TEMPLATE_PATHS = CollUtil.newHashSet(
JAVA_DOMAIN_TEMPLATE_PATH
, JAVA_VO_TEMPLATE_PATH
, JAVA_BO_TEMPLATE_PATH
, JAVA_MAPPER_TEMPLATE_PATH
, JAVA_SERVICE_TEMPLATE_PATH
, JAVA_SERVICE_IMPL_TEMPLATE_PATH
, JAVA_CONTROLLER_TEMPLATE_PATH
, XML_MAPPER_TEMPLATE_PATH
, TS_API_TEMPLATE_PATH
, TS_TYPES_TEMPLATE_PATH
, VUE_INDEX_TEMPLATE_PATH
, VUE_INDEX_TREE_TEMPLATE_PATH
, SQL_ORACLE_TEMPLATE_PATH
, SQL_POSTGRES_TEMPLATE_PATH
, SQL_SQLSERVER_TEMPLATE_PATH
, SQL_MYSQL_TEMPLATE_PATH
);
}

View File

@@ -6,13 +6,13 @@ import cn.hutool.core.io.IoUtil;
import com.baomidou.lock.annotation.Lock4j;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.common.redis.annotation.RepeatSubmit;
import org.dromara.common.web.core.BaseController;
import org.dromara.gen.domain.GenTable;
import org.dromara.gen.domain.GenTableColumn;
@@ -39,7 +39,11 @@ public class GenController extends BaseController {
private final IGenTableService genTableService;
/**
* 查询代码生成列表
* 分页查询代码生成业务列表
*
* @param genTable 查询条件
* @param pageQuery 分页参数
* @return 代码生成列表
*/
@SaCheckPermission("tool:gen:list")
@GetMapping("/list")
@@ -51,6 +55,7 @@ public class GenController extends BaseController {
* 修改代码生成业务
*
* @param tableId 表ID
* @return 表、字段与可选业务表信息
*/
@RepeatSubmit()
@SaCheckPermission("tool:gen:query")
@@ -67,7 +72,11 @@ public class GenController extends BaseController {
}
/**
* 查询数据库列表
* 分页查询数据库列表
*
* @param genTable 查询条件
* @param pageQuery 分页参数
* @return 数据库表列表
*/
@SaCheckPermission("tool:gen:list")
@GetMapping("/db/list")
@@ -79,6 +88,7 @@ public class GenController extends BaseController {
* 查询数据表字段列表
*
* @param tableId 表ID
* @return 字段列表
*/
@SaCheckPermission("tool:gen:list")
@GetMapping(value = "/column/{tableId}")
@@ -90,8 +100,9 @@ public class GenController extends BaseController {
/**
* 导入表结构(保存)
*
* @param tables 表名串
* @param tables 表名串
* @param dataName 数据源名称
* @return 操作结果
*/
@SaCheckPermission("tool:gen:import")
@Log(title = "代码生成", businessType = BusinessType.IMPORT)
@@ -107,7 +118,10 @@ public class GenController extends BaseController {
}
/**
* 修改保存代码生成业务
* 保存代码生成业务配置。
*
* @param genTable 业务配置
* @return 操作结果
*/
@SaCheckPermission("tool:gen:edit")
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
@@ -123,6 +137,7 @@ public class GenController extends BaseController {
* 删除代码生成
*
* @param tableIds 表ID串
* @return 操作结果
*/
@SaCheckPermission("tool:gen:remove")
@Log(title = "代码生成", businessType = BusinessType.DELETE)
@@ -136,6 +151,7 @@ public class GenController extends BaseController {
* 预览代码
*
* @param tableId 表ID
* @return 模板路径与生成代码内容映射
*/
@SaCheckPermission("tool:gen:preview")
@GetMapping("/preview/{tableId}")
@@ -147,6 +163,7 @@ public class GenController extends BaseController {
/**
* 生成代码(下载方式)
*
* @param response HTTP 响应
* @param tableId 表ID
*/
@SaCheckPermission("tool:gen:code")
@@ -161,6 +178,7 @@ public class GenController extends BaseController {
* 生成代码(自定义路径)
*
* @param tableId 表ID
* @return 操作结果
*/
@SaCheckPermission("tool:gen:code")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@@ -174,6 +192,7 @@ public class GenController extends BaseController {
* 同步数据库
*
* @param tableId 表ID
* @return 操作结果
*/
@SaCheckPermission("tool:gen:edit")
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
@@ -187,6 +206,7 @@ public class GenController extends BaseController {
/**
* 批量生成代码
*
* @param response HTTP 响应
* @param tableIdStr 表ID串
*/
@SaCheckPermission("tool:gen:code")
@@ -199,7 +219,10 @@ public class GenController extends BaseController {
}
/**
* 生成zip文件
* 生成结果写出为 zip 文件流。
*
* @param response HTTP 响应
* @param data zip 二进制数据
*/
private void genCode(HttpServletResponse response, byte[] data) throws IOException {
response.reset();
@@ -212,11 +235,13 @@ public class GenController extends BaseController {
}
/**
* 查询数据源名称列表
* 查询当前可用数据源名称列表
*
* @return 数据源名称集合
*/
@SaCheckPermission("tool:gen:list")
@GetMapping(value = "/getDataNames")
public R<Object> getCurrentDataSourceNameList(){
public R<Object> getCurrentDataSourceNameList() {
return R.ok(DataBaseHelper.getDataSourceNameList());
}
}

View File

@@ -12,7 +12,9 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.gen.constant.GenConstants;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 业务表 gen_table
@@ -152,7 +154,7 @@ public class GenTable extends BaseEntity {
@TableField(exist = false)
private String treeName;
/*
/**
* 菜单id列表
*/
@TableField(exist = false)
@@ -170,26 +172,67 @@ public class GenTable extends BaseEntity {
@TableField(exist = false)
private String parentMenuName;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
/**
* 判断当前业务表是否采用树表模板。
*
* @return 树表模板返回 {@code true}
*/
public boolean isTree() {
return isTree(this.tplCategory);
}
/**
* 根据模板分类判断是否为树表模板。
*
* @param tplCategory 模板分类
* @return 树表模板返回 {@code true}
*/
public static boolean isTree(String tplCategory) {
return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
}
/**
* 判断当前业务表是否采用普通 CRUD 模板。
*
* @return 普通 CRUD 模板返回 {@code true}
*/
public boolean isCrud() {
return isCrud(this.tplCategory);
}
/**
* 根据模板分类判断是否为普通 CRUD 模板。
*
* @param tplCategory 模板分类
* @return 普通 CRUD 模板返回 {@code true}
*/
public static boolean isCrud(String tplCategory) {
return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
}
/**
* 判断指定 Java 字段是否属于基类公共字段。
*
* @param javaField Java 字段名
* @return 基类公共字段返回 {@code true}
*/
public boolean isSuperColumn(String javaField) {
return isSuperColumn(this.tplCategory, javaField);
}
/**
* 根据模板分类与字段名判断是否属于基类公共字段。
*
* @param tplCategory 模板分类
* @param javaField Java 字段名
* @return 基类公共字段返回 {@code true}
*/
public static boolean isSuperColumn(String tplCategory, String javaField) {
return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
}

View File

@@ -122,70 +122,163 @@ public class GenTableColumn extends BaseEntity {
*/
private Integer sort;
/**
* 获取首字母大写后的 Java 字段名。
*
* @return 首字母大写的 Java 字段名
*/
public String getCapJavaField() {
return StringUtils.capitalize(javaField);
}
/**
* 判断当前列是否为主键列。
*
* @return 主键列返回 {@code true}
*/
public boolean isPk() {
return isPk(this.isPk);
}
/**
* 根据标识判断是否为主键列。
*
* @param isPk 主键标识
* @return 主键列返回 {@code true}
*/
public boolean isPk(String isPk) {
return isPk != null && StringUtils.equals("1", isPk);
}
/**
* 判断当前列是否为自增列。
*
* @return 自增列返回 {@code true}
*/
public boolean isIncrement() {
return isIncrement(this.isIncrement);
}
/**
* 根据标识判断是否为自增列。
*
* @param isIncrement 自增标识
* @return 自增列返回 {@code true}
*/
public boolean isIncrement(String isIncrement) {
return isIncrement != null && StringUtils.equals("1", isIncrement);
}
/**
* 判断当前列是否必填。
*
* @return 必填返回 {@code true}
*/
public boolean isRequired() {
return isRequired(this.isRequired);
}
/**
* 根据标识判断当前列是否必填。
*
* @param isRequired 必填标识
* @return 必填返回 {@code true}
*/
public boolean isRequired(String isRequired) {
return isRequired != null && StringUtils.equals("1", isRequired);
}
/**
* 判断当前列是否参与新增。
*
* @return 参与新增返回 {@code true}
*/
public boolean isInsert() {
return isInsert(this.isInsert);
}
/**
* 根据标识判断当前列是否参与新增。
*
* @param isInsert 新增标识
* @return 参与新增返回 {@code true}
*/
public boolean isInsert(String isInsert) {
return isInsert != null && StringUtils.equals("1", isInsert);
}
/**
* 判断当前列是否参与编辑。
*
* @return 参与编辑返回 {@code true}
*/
public boolean isEdit() {
return isEdit(this.isEdit);
}
/**
* 根据标识判断当前列是否参与编辑。
*
* @param isEdit 编辑标识
* @return 参与编辑返回 {@code true}
*/
public boolean isEdit(String isEdit) {
return isEdit != null && StringUtils.equals("1", isEdit);
}
/**
* 判断当前列是否参与列表展示。
*
* @return 参与列表展示返回 {@code true}
*/
public boolean isList() {
return isList(this.isList);
}
/**
* 根据标识判断当前列是否参与列表展示。
*
* @param isList 列表展示标识
* @return 参与列表展示返回 {@code true}
*/
public boolean isList(String isList) {
return isList != null && StringUtils.equals("1", isList);
}
/**
* 判断当前列是否参与查询条件。
*
* @return 参与查询返回 {@code true}
*/
public boolean isQuery() {
return isQuery(this.isQuery);
}
/**
* 根据标识判断当前列是否参与查询条件。
*
* @param isQuery 查询标识
* @return 参与查询返回 {@code true}
*/
public boolean isQuery(String isQuery) {
return isQuery != null && StringUtils.equals("1", isQuery);
}
/**
* 判断当前列是否为基类公共字段。
*
* @return 基类公共字段返回 {@code true}
*/
public boolean isSuperColumn() {
return isSuperColumn(this.javaField);
}
/**
* 根据字段名判断是否为基类公共字段。
*
* @param javaField Java 字段名
* @return 基类公共字段返回 {@code true}
*/
public static boolean isSuperColumn(String javaField) {
return StringUtils.equalsAnyIgnoreCase(javaField,
// BaseEntity
@@ -194,15 +287,31 @@ public class GenTableColumn extends BaseEntity {
"parentName", "parentId");
}
/**
* 判断当前列是否属于生成页面需要保留的白名单字段。
*
* @return 白名单字段返回 {@code true}
*/
public boolean isUsableColumn() {
return isUsableColumn(javaField);
}
/**
* 根据字段名判断是否属于生成页面需要保留的白名单字段。
*
* @param javaField Java 字段名
* @return 白名单字段返回 {@code true}
*/
public static boolean isUsableColumn(String javaField) {
// isSuperColumn()中的名单用于避免生成多余Domain属性若某些属性在生成页面时需要用到不能忽略则放在此处白名单
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
}
/**
* 从字段注释中解析字典读转换表达式。
*
* @return 形如 `0=男,1=女` 的转换表达式,无法解析时返回原始注释
*/
public String readConverterExp() {
String remarks = StringUtils.substringBetween(this.columnComment, "", "");
StringBuffer sb = new StringBuffer();

View File

@@ -15,10 +15,7 @@ import lombok.extern.slf4j.Slf4j;
import org.anyline.metadata.Column;
import org.anyline.metadata.Table;
import org.anyline.proxy.ServiceProxy;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
@@ -26,7 +23,6 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.mybatis.utils.IdGeneratorUtil;
import org.dromara.gen.constant.GenConstants;
import org.dromara.gen.domain.GenTable;
@@ -34,15 +30,14 @@ import org.dromara.gen.domain.GenTableColumn;
import org.dromara.gen.mapper.GenTableColumnMapper;
import org.dromara.gen.mapper.GenTableMapper;
import org.dromara.gen.util.GenUtils;
import org.dromara.gen.util.VelocityInitializer;
import org.dromara.gen.util.VelocityUtils;
import org.dromara.gen.util.TemplateEngineUtils;
import org.dromara.gen.util.template.PathNamedTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
@@ -61,7 +56,7 @@ public class GenTableServiceImpl implements IGenTableService {
private final GenTableMapper baseMapper;
private final GenTableColumnMapper genTableColumnMapper;
private static final String[] TABLE_IGNORE = new String[]{"sj_", "act_", "flw_", "gen_"};
private static final String[] TABLE_IGNORE = new String[]{"sj_", "flow_", "gen_"};
/**
* 查询业务字段列表
@@ -89,12 +84,25 @@ public class GenTableServiceImpl implements IGenTableService {
return genTable;
}
/**
* 分页查询已导入的代码生成业务表。
*
* @param genTable 业务表筛选条件
* @param pageQuery 分页参数
* @return 业务表分页结果
*/
@Override
public PageResult<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery) {
Page<GenTable> page = baseMapper.selectPage(pageQuery.build(), this.buildGenTableQueryWrapper(genTable));
return PageResult.build(page.getRecords(), page.getTotal());
}
/**
* 构造代码生成业务表查询条件。
*
* @param genTable 业务表筛选条件
* @return 包含数据源、表名、表注释和时间区间的查询包装器
*/
private QueryWrapper<GenTable> buildGenTableQueryWrapper(GenTable genTable) {
Map<String, Object> params = genTable.getParams();
QueryWrapper<GenTable> wrapper = Wrappers.query();
@@ -113,7 +121,7 @@ public class GenTableServiceImpl implements IGenTableService {
*
* @param genTable 包含查询条件的GenTable对象
* @param pageQuery 包含分页信息的PageQuery对象
* @return 包含分页结果的 PageResult 对象
* @return 包含分页结果的TableDataInfo对象
*/
@DS("#genTable.dataName")
@Override
@@ -166,6 +174,10 @@ public class GenTableServiceImpl implements IGenTableService {
return gen;
}).sorted(Comparator.comparing(GenTable::getCreateTime).reversed())
.toList();
// 根据原始数据列表和分页参数,构建表格分页数据对象(用于假分页)
if (CollUtil.isEmpty(tables)) {
return PageResult.build();
}
Page<Object> page = pageQuery.build();
List<GenTable> pageList = CollUtil.page((int) page.getCurrent() - 1, (int) page.getSize(), tables);
return PageResult.build(pageList, tables.size());
@@ -229,9 +241,7 @@ public class GenTableServiceImpl implements IGenTableService {
genTable.setOptions(options);
int row = baseMapper.updateById(genTable);
if (row > 0) {
for (GenTableColumn cenTableColumn : genTable.getColumns()) {
genTableColumnMapper.updateById(cenTableColumn);
}
genTableColumnMapper.updateBatchById(genTable.getColumns());
}
}
@@ -277,6 +287,7 @@ public class GenTableServiceImpl implements IGenTableService {
}
}
} catch (Exception e) {
log.error("导入失败", e);
throw new ServiceException("导入失败:" + e.getMessage());
}
}
@@ -320,27 +331,9 @@ public class GenTableServiceImpl implements IGenTableService {
@Override
public Map<String, String> previewCode(Long tableId) {
Map<String, String> dataMap = new LinkedHashMap<>();
// 查询表信息
GenTable table = getGenTable(tableId);
List<Long> menuIds = new ArrayList<>();
for (int i = 0; i < 6; i++) {
menuIds.add(IdGeneratorUtil.nextLongId());
}
table.setMenuIds(menuIds);
// 设置主键列信息
setPkColumn(table);
VelocityInitializer.initVelocity();
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
dataMap.put(template, sw.toString());
RenderContext rc = buildRenderContext(tableId);
for (PathNamedTemplate template : rc.templates()) {
dataMap.put(template.getPathName(), template.render(rc.context()));
}
return dataMap;
}
@@ -372,21 +365,18 @@ public class GenTableServiceImpl implements IGenTableService {
// 设置主键列信息
setPkColumn(table);
VelocityInitializer.initVelocity();
VelocityContext context = VelocityUtils.prepareContext(table);
Dict context = TemplateEngineUtils.buildContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
if (!StringUtils.containsAny(template, "sql.vm", "api.ts.vm", "types.ts.vm", "index.vue.vm", "index-tree.vue.vm")) {
List<PathNamedTemplate> templates = TemplateEngineUtils.getTemplateList(table.getTplCategory());
for (PathNamedTemplate template : templates) {
String pathName = template.getPathName();
// 渲染模板
if (!StringUtils.containsAny(pathName, "sql.vm", "api.ts.vm", "types.ts.vm", "index.vue.vm", "index-tree.vue.vm")) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
try {
String path = getGenPath(table, template);
FileUtils.writeUtf8String(sw.toString(), path);
String render = template.render(context);
String path = getGenPath(table, pathName);
FileUtils.writeUtf8String(render, path);
} catch (Exception e) {
throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
}
@@ -464,40 +454,47 @@ public class GenTableServiceImpl implements IGenTableService {
/**
* 查询表信息并生成代码
*
* @param tableId 业务表主键
* @param zip 代码压缩输出流
*/
private void generatorCode(Long tableId, ZipOutputStream zip) {
// 查询表信息
RenderContext rc = buildRenderContext(tableId);
GenTable table = rc.table();
for (PathNamedTemplate template : rc.templates()) {
String pathName = template.getPathName();
try {
String render = template.render(rc.context());
zip.putNextEntry(new ZipEntry(TemplateEngineUtils.getFileName(pathName, table)));
IoUtil.write(zip, StandardCharsets.UTF_8, false, render);
zip.flush();
zip.closeEntry();
} catch (IOException e) {
log.error("渲染模板失败,表名:{}", table.getTableName(), e);
}
}
}
/**
* 构建代码渲染上下文含表信息、菜单ID、主键列、模板列表
*
* @param tableId 业务表主键
* @return 渲染上下文
*/
private RenderContext buildRenderContext(Long tableId) {
GenTable table = getGenTable(tableId);
List<Long> menuIds = new ArrayList<>();
for (int i = 0; i < 6; i++) {
menuIds.add(IdGeneratorUtil.nextLongId());
}
table.setMenuIds(menuIds);
// 设置主键列信息
setPkColumn(table);
Dict context = TemplateEngineUtils.buildContext(table);
List<PathNamedTemplate> templates = TemplateEngineUtils.getTemplateList(table.getTplCategory());
return new RenderContext(table, context, templates);
}
VelocityInitializer.initVelocity();
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
try {
// 添加到zip
zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
IoUtil.close(sw);
zip.flush();
zip.closeEntry();
} catch (IOException e) {
log.error("渲染模板失败,表名:" + table.getTableName(), e);
}
}
private record RenderContext(GenTable table, Dict context, List<PathNamedTemplate> templates) {
}
/**
@@ -520,6 +517,12 @@ public class GenTableServiceImpl implements IGenTableService {
}
}
/**
* 查询业务表并补齐其列信息。
*
* @param tableId 业务表主键
* @return 包含字段集合的业务表实体
*/
private GenTable getGenTable(Long tableId) {
GenTable table = baseMapper.selectById(tableId);
if (ObjectUtil.isNull(table)) {
@@ -529,6 +532,12 @@ public class GenTableServiceImpl implements IGenTableService {
return table;
}
/**
* 批量填充业务表对应的字段列表。
*
* @param tables 业务表集合
* @return 已填充字段信息的业务表集合
*/
private List<GenTable> fillTableColumns(List<GenTable> tables) {
if (CollUtil.isEmpty(tables)) {
return tables;
@@ -596,9 +605,9 @@ public class GenTableServiceImpl implements IGenTableService {
public static String getGenPath(GenTable table, String template) {
String genPath = table.getGenPath();
if (StringUtils.equals(genPath, "/")) {
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
return System.getProperty("user.dir") + File.separator + "src" + File.separator + TemplateEngineUtils.getFileName(template, table);
}
return genPath + File.separator + VelocityUtils.getFileName(template, table);
return genPath + File.separator + TemplateEngineUtils.getFileName(template, table);
}
}

View File

@@ -1,7 +1,7 @@
package org.dromara.gen.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.gen.domain.GenTable;
import org.dromara.gen.domain.GenTableColumn;
@@ -26,16 +26,18 @@ public interface IGenTableService {
/**
* 查询业务列表
*
* @param genTable 业务信息
* @return 业务集合
* @param genTable 业务信息
* @param pageQuery 分页参数
* @return 业务分页集合
*/
PageResult<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery);
/**
* 查询据库列表
*
* @param genTable 业务信息
* @return 数据库表集合
* @param genTable 业务信息
* @param pageQuery 分页参数
* @return 数据库表分页集合
*/
PageResult<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery);

View File

@@ -3,8 +3,9 @@ package org.dromara.gen.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.RegExUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.gen.config.GenConfig;
import org.dromara.gen.config.properties.GenProperties;
import org.dromara.gen.constant.GenConstants;
import org.dromara.gen.domain.GenTable;
import org.dromara.gen.domain.GenTableColumn;
@@ -19,22 +20,29 @@ import java.util.Arrays;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class GenUtils {
private final static GenProperties PROPERTIES = SpringUtils.getBean(GenProperties.class);
/**
* 初始化表信息
*
* @param genTable 待初始化的业务表对象
*/
public static void initTable(GenTable genTable) {
genTable.setClassName(convertClassName(genTable.getTableName()));
genTable.setPackageName(GenConfig.getPackageName());
genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
genTable.setPackageName(PROPERTIES.getPackageName());
genTable.setModuleName(getModuleName(PROPERTIES.getPackageName()));
genTable.setBusinessName(getBusinessName(genTable.getTableName()));
genTable.setFunctionName(replaceText(genTable.getTableComment()));
genTable.setFunctionAuthor(GenConfig.getAuthor());
genTable.setFunctionAuthor(PROPERTIES.getAuthor());
genTable.setCreateTime(null);
genTable.setUpdateTime(null);
}
/**
* 初始化列属性字段
*
* @param column 待初始化的列对象
* @param table 所属业务表对象
*/
public static void initColumnField(GenTableColumn column, GenTable table) {
String dataType = getDbType(column.getColumnType());
@@ -152,8 +160,8 @@ public class GenUtils {
* @return 类名
*/
public static String convertClassName(String tableName) {
boolean autoRemovePre = GenConfig.getAutoRemovePre();
String tablePrefix = GenConfig.getTablePrefix();
boolean autoRemovePre = PROPERTIES.isAutoRemovePre();
String tablePrefix = PROPERTIES.getTablePrefix();
if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) {
String[] searchList = StringUtils.split(tablePrefix, StringUtils.SEPARATOR);
tableName = replaceFirst(tableName, searchList);
@@ -166,12 +174,13 @@ public class GenUtils {
*
* @param replacementm 替换值
* @param searchList 替换列表
* @return 去除命中前缀后的字符串
*/
public static String replaceFirst(String replacementm, String[] searchList) {
String text = replacementm;
for (String searchString : searchList) {
if (replacementm.startsWith(searchString)) {
text = replacementm.replaceFirst(searchString, StringUtils.EMPTY);
text = StringUtils.removeStart(replacementm, searchString);
break;
}
}
@@ -206,11 +215,15 @@ public class GenUtils {
* 获取字段长度
*
* @param columnType 列类型
* @return 截取后的列类型
* @return 字段长度,未声明长度时返回 0
*/
public static Integer getColumnLength(String columnType) {
if (StringUtils.indexOf(columnType, "(") > 0) {
String length = StringUtils.substringBetween(columnType, "(", ")");
// 处理 decimal(10,2) 这类带精度的类型,只取长度部分
if (length.contains(",")) {
length = StringUtils.substringBefore(length, ",");
}
return Integer.valueOf(length);
} else {
return 0;

View File

@@ -3,27 +3,34 @@ package org.dromara.gen.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.velocity.VelocityContext;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.enums.DataBaseType;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.gen.config.properties.GenProperties;
import org.dromara.gen.constant.GenConstants;
import org.dromara.gen.domain.GenTable;
import org.dromara.gen.domain.GenTableColumn;
import org.dromara.gen.util.template.PathNamedTemplate;
import java.util.*;
import java.util.function.Consumer;
import static org.dromara.gen.constant.GenConstants.TS_TYPES_TEMPLATE_PATH;
/**
* 模板处理工具
*
* @author ruoyi
* 模板引擎工具
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class VelocityUtils {
public class TemplateEngineUtils {
/**
* 项目空间路径
@@ -40,62 +47,102 @@ public class VelocityUtils {
*/
private static final String DEFAULT_PARENT_MENU_ID = "3";
// 模板引擎
private static final TemplateEngine TEMPLATE_ENGINE;
private static final Map<String, PathNamedTemplate> TEMPLATE_MAPPER;
static {
// 模板引擎初始化
GenProperties properties = SpringUtils.getBean(GenProperties.class);
TEMPLATE_ENGINE = TemplateUtil.createEngine(properties.getTemplateConfig());
TEMPLATE_MAPPER = PathNamedTemplate.form(TEMPLATE_ENGINE, GenConstants.TEMPLATE_PATHS);
}
/**
* 设置模板变量信息
* 构建模板上下文
*
* @return 模板列表
* @param contextInit 模板上下文初始化函数
* @return 模板上下文
*/
public static VelocityContext prepareContext(GenTable genTable) {
public static Dict buildContext(Consumer<Dict> contextInit) {
Dict context = new Dict();
contextInit.accept(context);
return context;
}
/**
* 构建模板上下文
*
* @param genTable 代码生成业务表对象
* @return 模板上下文
*/
public static Dict buildContext(GenTable genTable) {
// 构建上下文
Dict context = new Dict();
String moduleName = genTable.getModuleName();
String businessName = genTable.getBusinessName();
String packageName = genTable.getPackageName();
String tplCategory = genTable.getTplCategory();
String functionName = genTable.getFunctionName();
VelocityContext velocityContext = new VelocityContext();
velocityContext.put("tplCategory", genTable.getTplCategory());
velocityContext.put("tableName", genTable.getTableName());
velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
velocityContext.put("ClassName", genTable.getClassName());
velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
velocityContext.put("moduleName", genTable.getModuleName());
velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
velocityContext.put("businessName", genTable.getBusinessName());
velocityContext.put("basePackage", getPackagePrefix(packageName));
velocityContext.put("packageName", packageName);
velocityContext.put("author", genTable.getFunctionAuthor());
velocityContext.put("datetime", DateUtils.getDate());
velocityContext.put("pkColumn", genTable.getPkColumn());
velocityContext.put("importList", getImportList(genTable));
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
velocityContext.put("columns", genTable.getColumns());
velocityContext.put("table", genTable);
velocityContext.put("dicts", getDicts(genTable));
setMenuVelocityContext(velocityContext, genTable);
if (GenConstants.TPL_TREE.equals(tplCategory)) {
setTreeVelocityContext(velocityContext, genTable);
}
return velocityContext;
}
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) {
context.put("tplCategory", genTable.getTplCategory());
context.put("tableName", genTable.getTableName());
context.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
context.put("ClassName", genTable.getClassName());
context.put("className", StringUtils.uncapitalize(genTable.getClassName()));
context.put("moduleName", moduleName);
context.put("BusinessName", StringUtils.capitalize(businessName));
context.put("businessName", businessName);
context.put("basePackage", getPackagePrefix(packageName));
context.put("packageName", packageName);
context.put("author", genTable.getFunctionAuthor());
context.put("datetime", DateUtils.getDate());
context.put("pkColumn", genTable.getPkColumn());
context.put("importList", getImportList(genTable));
context.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
context.put("columns", genTable.getColumns());
context.put("table", genTable);
context.put("dicts", getDicts(genTable));
// 向模板上下文写入菜单相关变量
String options = genTable.getOptions();
Dict paramsObj = JsonUtils.parseMap(options);
String parentMenuId = getParentMenuId(paramsObj);
context.put("parentMenuId", parentMenuId);
// 向树形模板上下文写入树字段相关变量
if (GenConstants.TPL_TREE.equals(tplCategory)) {
setTreeContext(context, genTable, paramsObj);
}
return context;
}
public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) {
String options = genTable.getOptions();
Dict paramsObj = JsonUtils.parseMap(options);
String treeCode = getTreecode(paramsObj);
/**
* 向树形模板上下文写入树字段相关变量
*
* @param context 模板上下文
* @param genTable 代码生成业务表对象
* @param paramsObj 已解析的 options 参数避免重复解析
*/
public static void setTreeContext(Dict context, GenTable genTable, Dict paramsObj) {
String treeCode = getTreeCode(paramsObj);
String treeParentCode = getTreeParentCode(paramsObj);
String treeName = getTreeName(paramsObj);
context.put("treeCode", treeCode);
context.put("treeParentCode", treeParentCode);
context.put("treeName", treeName);
context.put("expandColumn", getExpandColumn(genTable));
String expandTreeName = paramsObj.getStr(GenConstants.TREE_NAME);
int expandColumn = 0;
for (GenTableColumn column : genTable.getColumns()) {
if (column.isList()) {
expandColumn++;
if (column.getColumnName().equals(expandTreeName)) {
break;
}
}
}
context.put("expandColumn", expandColumn);
if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
context.put("tree_parent_code", paramsObj.get(GenConstants.TREE_PARENT_CODE));
}
@@ -109,38 +156,48 @@ public class VelocityUtils {
*
* @return 模板列表
*/
public static List<String> getTemplateList(String tplCategory) {
List<String> templates = new ArrayList<>();
templates.add("vm/java/domain.java.vm");
templates.add("vm/java/vo.java.vm");
templates.add("vm/java/bo.java.vm");
templates.add("vm/java/mapper.java.vm");
templates.add("vm/java/service.java.vm");
templates.add("vm/java/serviceImpl.java.vm");
templates.add("vm/java/controller.java.vm");
templates.add("vm/xml/mapper.xml.vm");
public static List<PathNamedTemplate> getTemplateList(String tplCategory) {
List<PathNamedTemplate> templates = new ArrayList<>();
// 后端源码模板
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_DOMAIN_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_VO_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_BO_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_MAPPER_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_SERVICE_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_SERVICE_IMPL_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_CONTROLLER_TEMPLATE_PATH));
// MyBatis MapperXML 模板
templates.add(TEMPLATE_MAPPER.get(GenConstants.XML_MAPPER_TEMPLATE_PATH));
// 前端接口源码模板
templates.add(TEMPLATE_MAPPER.get(GenConstants.TS_API_TEMPLATE_PATH));
templates.add(TEMPLATE_MAPPER.get(TS_TYPES_TEMPLATE_PATH));
// 数据库模板
DataBaseType dataBaseType = DataBaseHelper.getDataBaseType();
if (dataBaseType.isOracle()) {
templates.add("vm/sql/oracle/sql.vm");
templates.add(TEMPLATE_MAPPER.get(GenConstants.SQL_ORACLE_TEMPLATE_PATH));
} else if (dataBaseType.isPostgreSql()) {
templates.add("vm/sql/postgres/sql.vm");
templates.add(TEMPLATE_MAPPER.get(GenConstants.SQL_POSTGRES_TEMPLATE_PATH));
} else if (dataBaseType.isSqlServer()) {
templates.add("vm/sql/sqlserver/sql.vm");
templates.add(TEMPLATE_MAPPER.get(GenConstants.SQL_SQLSERVER_TEMPLATE_PATH));
} else {
templates.add("vm/sql/sql.vm");
// 默认使用MySQL模板
templates.add(TEMPLATE_MAPPER.get(GenConstants.SQL_MYSQL_TEMPLATE_PATH));
}
templates.add("vm/ts/api.ts.vm");
templates.add("vm/ts/types.ts.vm");
// 前端页面源码模板
if (GenConstants.TPL_CRUD.equals(tplCategory)) {
templates.add("vm/vue/index.vue.vm");
templates.add(TEMPLATE_MAPPER.get(GenConstants.VUE_INDEX_TEMPLATE_PATH));
} else if (GenConstants.TPL_TREE.equals(tplCategory)) {
templates.add("vm/vue/index-tree.vue.vm");
templates.add(TEMPLATE_MAPPER.get(GenConstants.VUE_INDEX_TREE_TEMPLATE_PATH));
}
return templates;
}
/**
* 获取文件名
*
* @param template 模板路径
* @param genTable 代码生成业务表对象
* @return 模板对应的目标文件相对路径
*/
public static String getFileName(String template, GenTable genTable) {
// 文件名称
@@ -157,17 +214,15 @@ public class VelocityUtils {
String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
String mybatisPath = MYBATIS_PATH + "/" + moduleName;
String vuePath = "vue";
// templatePath
// genFilePathFormat
if (template.contains("domain.java.vm")) {
fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
}
if (template.contains("vo.java.vm")) {
} else if (template.contains("vo.java.vm")) {
fileName = StringUtils.format("{}/domain/vo/{}Vo.java", javaPath, className);
}
if (template.contains("bo.java.vm")) {
} else if (template.contains("bo.java.vm")) {
fileName = StringUtils.format("{}/domain/bo/{}Bo.java", javaPath, className);
}
if (template.contains("mapper.java.vm")) {
} else if (template.contains("mapper.java.vm")) {
fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
} else if (template.contains("service.java.vm")) {
fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
@@ -289,7 +344,7 @@ public class VelocityUtils {
* @param paramsObj 生成其他选项
* @return 树编码
*/
public static String getTreecode(Map<String, Object> paramsObj) {
public static String getTreeCode(Map<String, Object> paramsObj) {
if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_CODE)) {
return StringUtils.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_CODE)));
}
@@ -321,27 +376,4 @@ public class VelocityUtils {
}
return StringUtils.EMPTY;
}
/**
* 获取需要在哪一列上面显示展开按钮
*
* @param genTable 业务表对象
* @return 展开按钮列序号
*/
public static int getExpandColumn(GenTable genTable) {
String options = genTable.getOptions();
Dict paramsObj = JsonUtils.parseMap(options);
String treeName = paramsObj.getStr(GenConstants.TREE_NAME);
int num = 0;
for (GenTableColumn column : genTable.getColumns()) {
if (column.isList()) {
num++;
String columnName = column.getColumnName();
if (columnName.equals(treeName)) {
break;
}
}
}
return num;
}
}

View File

@@ -1,35 +0,0 @@
package org.dromara.gen.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.velocity.app.Velocity;
import org.dromara.common.core.constant.Constants;
import java.util.Properties;
/**
* VelocityEngine工厂
*
* @author ruoyi
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class VelocityInitializer {
/**
* 初始化vm方法
*/
public static void initVelocity() {
Properties p = new Properties();
try {
// 加载classpath目录下的vm文件
p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 定义字符集
p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
// 初始化Velocity引擎指定配置Properties
Velocity.init(p);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,68 @@
package org.dromara.gen.util.template;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateEngine;
import lombok.Getter;
import java.io.File;
import java.io.OutputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 基于路径命名的模板委托实现
*
* @author 秋辞未寒
*/
public class PathNamedTemplate implements Template {
@Getter
private final String pathName;
private final Template delegate;
private PathNamedTemplate(String pathName, Template delegate) {
this.pathName = pathName;
this.delegate = delegate;
}
@Override
public void render(Map<?, ?> bindingMap, Writer writer) {
delegate.render(bindingMap, writer);
}
@Override
public void render(Map<?, ?> bindingMap, OutputStream out) {
delegate.render(bindingMap, out);
}
@Override
public void render(Map<?, ?> bindingMap, File file) {
delegate.render(bindingMap, file);
}
@Override
public String render(Map<?, ?> bindingMap) {
return delegate.render(bindingMap);
}
public static PathNamedTemplate form(String pathName, Template delegate) {
return new PathNamedTemplate(pathName, delegate);
}
public static PathNamedTemplate form(TemplateEngine templateEngine,String pathName) {
return new PathNamedTemplate(pathName,templateEngine.getTemplate(pathName));
}
public static Map<String, PathNamedTemplate> form(TemplateEngine templateEngine, Set<String> pathNames) {
Map<String, PathNamedTemplate> result = new HashMap<>();
for (String pathName : pathNames) {
PathNamedTemplate pathNamedTemplate = form(templateEngine, pathName);
result.put(pathName, pathNamedTemplate);
}
return result;
}
}