代码生成器

源码

表结构

代码的目录结构

后端代码

前端代码

查询数据库的表

前端




后端

  • 只查询当前数据库的表
  • 去除掉定时任务和生成器的表格
  • 去除掉已经导入的表格
xml 复制代码
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
	select table_name, table_comment, create_time, update_time 
	from information_schema.tables
	where table_schema = (select database()) <!-- 查询当前数据库中的表 -->
	AND table_name NOT LIKE 'qrtz_%' <!-- 排除表名以 'qrtz_' 开头的表 -->
	AND table_name NOT LIKE 'gen_%' <!-- 排除表名以 'gen_' 开头的表 -->
	AND table_name NOT IN (select table_name from gen_table) <!-- 排除已经在 gen_table 表中的表 -->
	<if test="tableName != null and tableName != ''">
		AND lower(table_name) like lower(concat('%', #{tableName}, '%')) <!-- 如果 tableName 不为空,按表名模糊查询 -->
	</if>
	<if test="tableComment != null and tableComment != ''">
		AND lower(table_comment) like lower(concat('%', #{tableComment}, '%')) <!-- 如果 tableComment 不为空,按表注释模糊查询 -->
	</if>
	<if test="params.beginTime != null and params.beginTime != ''"><!-- 如果 beginTime 不为空,按创建时间起始时间查询 -->
		AND date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
	</if>
	<if test="params.endTime != null and params.endTime != ''"><!-- 如果 endTime 不为空,按创建时间结束时间查询 -->
		AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
	</if>
	order by create_time desc <!-- 按创建时间降序排列 -->
</select>

导入表结构

流程

前端

对选中的表进行处理

导入表的后端接口

后端

controller

mapper层

导入表结构的 数据库代码

  • 循环遍历 前端传入的数据
  • 存储表的信息
  • 存储列的信息
java 复制代码
 for (GenTable table : tableList)
 {
     String tableName = table.getTableName();
     // 初始化表信息
     GenUtils.initTable(table, operName);
     // 插入表信息
     int row = genTableMapper.insertGenTable(table);
     if (row > 0)
     {
         // 保存列信息
         List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
         for (GenTableColumn column : genTableColumns)
         {
             GenUtils.initColumnField(column, table);
             genTableColumnMapper.insertGenTableColumn(column);
         }
     }
 }

获取列信息的mapper

xml 复制代码
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
    <!-- 选择列的详细信息 -->
    select column_name,
        <!-- 判断列是否为必需(不可为空且不是主键) -->
        (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required,
        <!-- 判断列是否为主键 -->
        (case when column_key = 'PRI' then '1' else '0' end) as is_pk,
        <!-- 获取列的序号位置 -->
        ordinal_position as sort,
        <!-- 获取列的注释 -->
        column_comment,
        <!-- 判断列是否为自动递增 -->
        (case when extra = 'auto_increment' then '1' else '0' end) as is_increment,
        <!-- 获取列的数据类型 -->
        column_type
    from information_schema.columns
    <!-- 过滤当前数据库模式中指定表的列 -->
    where table_schema = (select database())
        and table_name = (#{tableName})
    <!-- 按列的序号位置排序 -->
    order by ordinal_position
    </select>

初始化 列的信息

  • 根据数据库的列名使用驼峰命名法进行设置
  • 根据 原本的 列类型 设置对应的 java的类型
  • 根据 列的名称 判断 大致的 前段的 筛选 条件的方式,是EQ,LIKE,RADIO
java 复制代码
public static void initColumnField(GenTableColumn column, GenTable table)
    {
        // 获取列的数据类型
        String dataType = getDbType(column.getColumnType());
        // 获取列的名称
        String columnName = column.getColumnName();
        // 设置表ID
        column.setTableId(table.getTableId());
        // 设置创建者
        column.setCreateBy(table.getCreateBy());
        // 设置Java字段名
        column.setJavaField(StringUtils.toCamelCase(columnName));
        // 设置默认Java类型为String,默认查询方式为EQ
        column.setJavaType(GenConstants.TYPE_STRING);
        column.setQueryType(GenConstants.QUERY_EQ);
    
        // 根据数据类型设置HTML类型
        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
        {
            // 如果字符串长度超过500,设置为文本域,否则设置为输入框
            Integer columnLength = getColumnLength(column.getColumnType());
            String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
            column.setHtmlType(htmlType);
        }
        else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
        {
            // 时间类型设置Java类型为Date,HTML类型为DATETIME
            column.setJavaType(GenConstants.TYPE_DATE);
            column.setHtmlType(GenConstants.HTML_DATETIME);
        }
        else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
        {
            // 数字类型设置HTML类型为输入框
            column.setHtmlType(GenConstants.HTML_INPUT);
    
            // 如果是浮点型,设置Java类型为BigDecimal
            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
            {
                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
            }
            // 如果是整型,且长度小于等于10,设置Java类型为Integer
            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
            {
                column.setJavaType(GenConstants.TYPE_INTEGER);
            }
            // 否则设置为Long类型
            else
            {
                column.setJavaType(GenConstants.TYPE_LONG);
            }
        }
    
        // 默认所有字段都需要插入
        column.setIsInsert(GenConstants.REQUIRE);
    
        // 如果列名不在不可编辑列表中且不是主键,设置为可编辑
        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
        {
            column.setIsEdit(GenConstants.REQUIRE);
        }
        // 如果列名不在不可列表中且不是主键,设置为列表字段
        if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
        {
            column.setIsList(GenConstants.REQUIRE);
        }
        // 如果列名不在不可查询列表中且不是主键,设置为查询字段
        if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
        {
            column.setIsQuery(GenConstants.REQUIRE);
        }
    
        // 如果列名以name结尾,设置查询类型为LIKE
        if (StringUtils.endsWithIgnoreCase(columnName, "name"))
        {
            column.setQueryType(GenConstants.QUERY_LIKE);
        }
        // 如果列名以status结尾,设置HTML类型为单选框
        if (StringUtils.endsWithIgnoreCase(columnName, "status"))
        {
            column.setHtmlType(GenConstants.HTML_RADIO);
        }
        // 如果列名以type或sex结尾,设置HTML类型为下拉框
        else if (StringUtils.endsWithIgnoreCase(columnName, "type") || StringUtils.endsWithIgnoreCase(columnName, "sex"))
        {
            column.setHtmlType(GenConstants.HTML_SELECT);
        }
        // 如果列名以image结尾,设置HTML类型为图片上传控件
        else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
        {
            column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
        }
        // 如果列名以file结尾,设置HTML类型为文件上传控件
        else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
        {
            column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
        }
        // 如果列名以content结尾,设置HTML类型为富文本控件
        else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
        {
            column.setHtmlType(GenConstants.HTML_EDITOR);
        }
    }

批量生成代码

controller层

Service层

  • 创建一个zip流
  • 遍历表名,依次生成对应的代码
java 复制代码
    @Override
    public byte[] downloadCode(String[] tableNames)
    {
        // 创建一个字节数组输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 创建一个Zip输出流
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        // 遍历所有表名,生成代码并添加到Zip输出流中
        for (String tableName : tableNames)
        {
            generatorCode(tableName, zip);
        }
        // 关闭Zip输出流
        IOUtils.closeQuietly(zip);
        // 返回生成的字节数组
        return outputStream.toByteArray();
    }

获取 上下文模板文件

将上下文的内容加到写到模板文件中

使用response输出流输出zip文件

java 复制代码
private void genCode(HttpServletResponse response, byte[] data) throws IOException
{
    // 重置响应以清除任何先前的数据
    response.reset();
    // 允许跨域请求
    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);
    // 设置内容类型以指示二进制文件
    response.setContentType("application/octet-stream; charset=UTF-8");
    // 将数据写入响应输出流
    IOUtils.write(data, response.getOutputStream());
}
相关推荐
wowocpp3 分钟前
idea springboot 配置文件 中文显示
java·spring boot·intellij-idea
User_芊芊君子6 分钟前
【Java面试题】——this 和 super 的区别
java·开发语言
柴薪之王、睥睨众生7 分钟前
(自用)Java学习-5.8(总结,springboot)
java·开发语言·spring boot·学习·mybatis
牛马baby7 分钟前
Java高频面试之并发编程-17
java·开发语言·面试
不辉放弃1 小时前
java连数据库
java·mysql
熊大如如8 小时前
Java 反射
java·开发语言
猿来入此小猿9 小时前
基于SSM实现的健身房系统功能实现十六
java·毕业设计·ssm·毕业源码·免费学习·猿来入此·健身平台
goTsHgo9 小时前
Spring Boot 自动装配原理详解
java·spring boot
卑微的Coder10 小时前
JMeter同步定时器 模拟多用户并发访问场景
java·jmeter·压力测试
pjx98710 小时前
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
java·spring cloud·微服务·eureka