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之代码生成(二)/
发布于
2024年4月15日
更新于
2024年4月21日
许可协议