ruoyi-vue-plus之代码生成(二)
本文主要将分析数据库字段以及下载生成的代码
文档地址:点击这里
项目地址:点击这里
功能介绍:点击这里
简单介绍
对于该项目的代码生成,只需在项目数据库中把表创建好,然后将表添加到生成列表即可。如果表添加成功,则会在gen_table中生成一条数据,这条数据对应着表信息;以及在gen_table_column生成一条数据,这条数据对应表的字段信息。
数据库字段的分析
1.代码生成业务表
drop table if exists gen_table;
create table gen_table (
table_id bigint(20) not null comment '编号',
table_name varchar(200) default '' comment '表名称',
table_comment varchar(500) default '' comment '表描述',
sub_table_name varchar(64) default null comment '关联子表的表名',
sub_table_fk_name varchar(64) default null comment '子表关联的外键名',
class_name varchar(100) default '' comment '实体类名称',
tpl_category varchar(200) default 'crud' comment '使用的模板(crud单表操作 tree树表操作)',
package_name varchar(100) comment '生成包路径',
module_name varchar(30) comment '生成模块名',
business_name varchar(30) comment '生成业务名',
function_name varchar(50) comment '生成功能名',
function_author varchar(50) comment '生成功能作者',
gen_type char(1) default '0' comment '生成代码方式(0zip压缩包 1自定义路径)',
gen_path varchar(200) default '/' comment '生成路径(不填默认项目路径)',
options varchar(1000) comment '其它生成选项',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default null comment '备注',
primary key (table_id)
) engine=innodb comment = '代码生成业务表';
2.代码生成业务表字段
drop table if exists gen_table_column;
create table gen_table_column (
column_id bigint(20) not null comment '编号',
table_id bigint(20) comment '归属表编号',
column_name varchar(200) comment '列名称',
column_comment varchar(500) comment '列描述',
column_type varchar(100) comment '列类型',
java_type varchar(500) comment 'JAVA类型',
java_field varchar(200) comment 'JAVA字段名',
is_pk char(1) comment '是否主键(1是)',
is_increment char(1) comment '是否自增(1是)',
is_required char(1) comment '是否必填(1是)',
is_insert char(1) comment '是否为插入字段(1是)',
is_edit char(1) comment '是否编辑字段(1是)',
is_list char(1) comment '是否列表字段(1是)',
is_query char(1) comment '是否查询字段(1是)',
query_type varchar(200) default 'EQ' comment '查询方式(等于、不等于、大于、小于、范围)',
html_type varchar(200) comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
dict_type varchar(200) default '' comment '字典类型',
sort int comment '排序',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
primary key (column_id)
) engine=innodb comment = '代码生成业务表字段';
3.字段解释
引入包以及导入包
每生成一个类都必须要有的东西:那就是引入包名和导入包。为什么不添加importList字段呢,我个人认为,创建importList需要额外的一些操作。
/**
* 根据列类型获取导入包
*
* @param genTable 业务表对象
* @return 返回需要导入的包列表
*/
public static HashSet<String> getImportList(GenTable genTable) {
List<GenTableColumn> columns = genTable.getColumns();
GenTable subGenTable = genTable.getSubTable();
HashSet<String> importList = new HashSet<>();
if (ObjectUtil.isNotNull(subGenTable)) {
importList.add("java.util.List");
}
for (GenTableColumn column : columns) {
if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) {
importList.add("java.util.Date");
importList.add("com.fasterxml.jackson.annotation.JsonFormat");
} else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) {
importList.add("java.math.BigDecimal");
}
}
return importList;
}
注释
/**
* OSS对象存储对象 sys_oss
*
* @author ruoyi
* @date 2024-04-15
*/
OSS对象存储(function_name) 对象 sys_oss(table_name)
ruoyi(function_author)
2024-04-15(dateTimeNow(YYYY_MM_DD),这里不用create_time,因为会显示时分秒)
注解
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_oss")
sys_oss(table_name)
类名以及属性
entity
public class SysOss extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 对象存储主键
*/
@TableId(value = "oss_id")
private Long ossId;
/**
* 文件名
*/
private String fileName;
/**
* 原名
*/
private String originalName;
/**
* 文件后缀名
*/
private String fileSuffix;
/**
* URL地址
*/
private String url;
/**
* 服务商
*/
private String service;
}
Bo
public class SysOssBo extends BaseEntity {
/**
* 对象存储主键
*/
@NotNull(message = "对象存储主键不能为空", groups = { EditGroup.class })
private Long ossId;
/**
* 文件名
*/
@NotBlank(message = "文件名不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileName;
/**
* 原名
*/
@NotBlank(message = "原名不能为空", groups = { AddGroup.class, EditGroup.class })
private String originalName;
/**
* 文件后缀名
*/
@NotBlank(message = "文件后缀名不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileSuffix;
/**
* URL地址
*/
@NotBlank(message = "URL地址不能为空", groups = { AddGroup.class, EditGroup.class })
private String url;
/**
* 服务商
*/
@NotBlank(message = "服务商不能为空", groups = { AddGroup.class, EditGroup.class })
private String service;
}
groups = { AddGroup.class, EditGroup.class },中括号里的内容是变量Group,是根据is_edit,is_insert字段的内容来设置的。
小结
看哪些内容是与表或类有关联的,则设置字段。剩余的都是固定的,在vm文件上写死即可。
其他的Controller、Service、Vo等等都是如此。
4.下载生成的代码
控制层方法:
可以选择多张表,批量生成代码,生成的文件名为:ruoyi.zip
/**
* 批量生成代码(下载方式)
* @param response 响应体
* @param tables 表名串
*/
@SaCheckPermission("tool:gen:code")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/batchGenCode")
public void batchGenCode(HttpServletResponse response, String[] tables) throws IOException {
// 将字符串转换为字符串数组
String[] tableNames = Convert.toStrArray(tables);
byte[] data = genTableService.downloadCode(tableNames);
genCode(response, data);
}
/**
* 生成zip文件
*/
private void genCode(HttpServletResponse response, byte[] data) throws IOException {
// 清除响应缓冲区中存在的任何数据
response.reset();
// 将CORS标头设置为允许来自任何来源的请求
response.addHeader("Access-Control-Allow-Origin", "*");
// 表示将Content-Disposition暴露给客户端
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
// 将Content-Disposition标头设置为指示响应应被视为附件下载,文件名为ruoyi.zip
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
// 将Content-Length标头设置为响应中发送数据的长度
response.addHeader("Content-Length", "" + data.length);
// 将Content-Type标头设置为指示发送的内容为application/octet-stream,即二进制文件,并使用UTF-8编码
response.setContentType("application/octet-stream; charset=UTF-8");
IoUtil.write(response.getOutputStream(), false, data);
}
服务层方法:
/**
* 批量生成代码(下载方式)
*
* @param tableNames 表数组
* @return 数据
*/
@Override
public byte[] downloadCode(String[] tableNames) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 新建zip输出流对象
ZipOutputStream zip = new ZipOutputStream(outputStream);
// 循环每张表
for (String tableName : tableNames) {
generatorCode(tableName, zip);
}
// 关闭流
IoUtil.close(zip);
return outputStream.toByteArray();
}
/**
* 生成代码(自定义路径)
* @param zip ZipOutputStream
* @param tableName 表名称
*/
private void generatorCode(ZipOutputStream zip, String tableName) {
LinkedHashMap<String, String> dataMap = new LinkedHashMap<>();
// 查询表信息
GenTable table = genTableMapper.selectGenTableByName(tableName);
// 设置表信息
setGenTable(table);
// 初始化模版引擎
VelocityInitializer.initVelocity();
// 在上下文中设置模版变量
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模版信息
List<String> templateList = VelocityUtils.getTemplateList(tableName);
for (String template : templateList) {
// 渲染模版
StringWriter sw = new StringWriter();
Template tp1 = Velocity.getTemplate(template, Constants.UTF8);
// 用于合并模板(template)与上下文(context)并将结果写入到sw对象中
tp1.merge(context, sw);
try {
//添加到zip
zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
// 把sw.toString()的内容写到zip输出流中,被设置编码为UTF-8,false为不关闭流
IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
IoUtil.close(sw);
// 刷新
zip.flush();
zip.closeEntry();
} catch (IOException e) {
log.error("渲染模板失败,表名:" + table.getTableName(), e);
}
}
}
/**
* 设置表信息
* @param table 表
*/
private void setGenTable(GenTable table) {
// 设置菜单id列表
ArrayList<Long> menuIds = new ArrayList<>();
for (int i = 0; i < 6; i++) {
// 把生成id(雪花算法)添加到列表
menuIds.add(identifierGenerator.nextId(null).longValue());
}
table.setMenuIds(menuIds);
// 设置主子表信息
setSubTable(table);
// 设置主键信息
setPKColumn(table);
}
ruoyi-vue-plus之代码生成(二)
http://example.com/2024/04/15/ruoyi-vue-plus之代码生成(二)/