代码生成器

源码

表结构

代码的目录结构

后端代码

前端代码

查询数据库的表

前端




后端

  • 只查询当前数据库的表
  • 去除掉定时任务和生成器的表格
  • 去除掉已经导入的表格
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());
}
相关推荐
面朝大海,春不暖,花不开19 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y19 分钟前
Java安全点safepoint
java
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java
白宇横流学长2 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
fat house cat_2 小时前
【redis】线程IO模型
java·redis
stein_java3 小时前
springMVC-10验证及国际化
java·spring
weixin_478689763 小时前
C++ 对 C 的兼容性
java·c语言·c++