若依源码解析:代码生成ruoyi-generator

news2024/12/23 0:30:08

文章目录

  • 摘要
  • 代码生成器的使用
    • 数据库连接配置
    • 数据库表设计
    • 代码生成器配置
      • 修改mybatis别名配置,增加对com.cyl包名的识别
      • 修改mybatis的mapper扫描包路径
    • 代码生成
    • 代码输出
    • 模板配置
  • 代码生成器原理
    • 模板引擎:Velocity
      • 使用Velocity模板引擎的一般流程
      • 模板语法
      • 上下文数据
    • information_schema
  • 源码解析
    • 导入表结构(com.ruoyi.generator.controller.GenController#importTableSave接口)
    • 生成代码(com.ruoyi.generator.controller.GenController#batchGenCode接口)
    • generatorCoded方法

摘要

若依的代码生成器模块(ruoyi-generator)可以根据数据库表的设计信息和配置的模板,自动生成相应的Java代码文件。代码生成器使用Velocity作为模板引擎,根据模板文件中的占位符和变量替换规则,将元数据信息嵌入到生成的代码中,生成具体的代码文件。通过导入表结构和生成代码两个后端接口,实现了快速导入数据库表结构和生成代码的功能。导入表结构会从information_schema数据库的tables和columns表中查询表和列的信息,并插入到ruoyi数据库的gen_table和gen_table_column表中。生成代码时,会根据查询到的表和列信息,初始化Velocity模板引擎,并准备上下文信息,包括变量值信息。然后,读取模板文件,渲染模板,并将渲染后的内容添加到压缩流中生成zip压缩文件,供前端下载使用。ruoyi-vue代码生成器大大提高了开发效率,使得开发人员能够快速生成符合规范的代码文件。

代码生成器的使用

通过以下步骤,若依可以根据数据库表的设计信息自动生成相应的代码文件,极大地提高了开发效率。开发人员可以根据生成的代码文件进行进一步的开发和定制。

以下是若依实现代码自动生成的一般流程:

数据库连接配置

首先,若依需要配置数据库连接信息,包括数据库类型、地址、用户名和密码等。
在这里插入图片描述

数据库表设计

在数据库中设计和定义表结构,包括表名、字段名、数据类型、约束等。
若依建表有个要求:表字段 和 表,都需要加注释,注释就是生成页面的显示内容

CREATE TABLE `goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `GOODS_NAME` varchar(255) DEFAULT NULL COMMENT '商品名字',
  `put_way_flag` tinyint(1) DEFAULT NULL COMMENT '商品是否上架,0:下架,1:上架',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'

代码生成器配置

若依提供了一个代码生成器,通过application.yml配置文件可以设置生成器的参数,如生成路径、包名、作者等。

# 代码生成
gen: 
  # 作者
  author: zcc
  # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
  packageName: com.cyl.pms
  # 自动去除表前缀,默认是false
  autoRemovePre: false
  # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
  tablePrefix: pms_

另外,这里要使用自定义包名com.cyl.pms,所以若依系统中mybatis也要做相应的修改

修改mybatis别名配置,增加对com.cyl包名的识别

# MyBatis配置
mybatis:
    # 搜索指定包别名
    typeAliasesPackage: com.ruoyi.**.domain,com.cyl.**.domain

修改mybatis的mapper扫描包路径

修改com.ruoyi.framework.config.ApplicationConfig类的MapperScan注解,增加对com.cyl包的扫描

@MapperScan({"com.ruoyi.**.mapper","com.cyl.**.mapper"})
public class ApplicationConfig{
    ...
}

代码生成

若依根据配置和模板,通过解析数据库表的元数据信息,自动生成对应的Java类、Mapper接口、Service类、Controller类等代码文件。
进入系统工具-代码生成页面,点击导入按钮,找到goods表并导入,如下图所示
在这里插入图片描述
点击编辑按钮之后,跳转修改生成配置页面。
在这里插入图片描述
在这里插入图片描述
点击生成代码按钮
在这里插入图片描述

代码输出

生成的代码文件可以输出到指定的目录中,可以选择直接写入磁盘文件或者打包成压缩文件。
生成的代码目录结构如下所示

├── goodsMenu.sql
├── main
│   ├── java
│   │   └── com
│   │       └── kdyzm
│   │           └── business
│   │               ├── controller
│   │               │   └── GoodsController.java
│   │               ├── domain
│   │               │   └── Goods.java
│   │               ├── mapper
│   │               │   └── GoodsMapper.java
│   │               └── service
│   │                   ├── IGoodsService.java
│   │                   └── impl
│   │                       └── GoodsServiceImpl.java
│   └── resources
│       └── mapper
│           └── business
│               └── GoodsMapper.xml
└── vue
    ├── api
    │   └── business
    │       └── goods.js
    └── views
        └── business
            └── goods
                └── index.vue

模板配置

若依代码生成器支持三种数据格式模板的代码生成:单表、树表、主子表,一般默认使用的是单表模板,也是最常使用的模板。
在这里插入图片描述

代码生成器原理

模板引擎:Velocity

在若依(Ruoyi)项目的代码生成中,使用了Apache Velocity作为模板引擎来生成具体的代码。

使用Velocity模板引擎的一般流程

Velocity是一个Java模板引擎,它使用简单的模板语法和变量替换规则来生成文本输出。以下是若依项目中使用Velocity模板引擎的一般流程:

  1. 引入Velocity依赖:
    首先,在项目的构建文件中(如pom.xml)添加Velocity的依赖项,以便在代码中使用Velocity的相关类和方法。

  2. 获取模板:
    在代码生成过程中,若依会根据配置的模板文件路径,使用Velocity模板引擎获取指定的模板。通常,模板文件以.vm为后缀,如xxx.java.vm表示Java类的模板。

  3. 创建Velocity模板引擎对象:
    若依通过Velocity.getTemplate(template, charset)方法创建Velocity模板引擎对象。template参数是模板文件的路径,charset参数是模板文件的字符编码。

  4. 准备上下文数据:
    在代码生成过程中,若依会准备一些上下文数据,以便在模板中使用。这些数据通常包括表信息、字段信息和其他生成参数等。上下文数据被封装在一个context对象中,可以通过context.put(key, value)方法添加到上下文中。

  5. 渲染模板:
    使用Template.merge(context, writer)方法,将上下文数据应用于模板,并将渲染后的结果写入指定的输出writer中。在若依中,通常使用StringWriter作为输出的writer,以便将渲染后的代码保存为字符串。

  6. 获取渲染结果:
    通过StringWriter.toString()方法获取渲染后的代码字符串,即生成的具体代码。

  7. 输出代码:
    生成的代码可以输出到指定的路径或文件中。若依中使用FileUtils.writeStringToFile(file, content, charset)方法将代码字符串写入文件中。

模板语法

Velocity模板引擎使用简洁而强大的模板语法。在若依项目中,模板文件通常采用.java.vm的后缀,表示Java类的模板。在模板文件中,可以使用Velocity的标签、变量和指令来定义动态内容和控制流程。

一些常用的Velocity模板语法包括:

  • 变量替换:使用${variable}来引用变量。
  • 条件语句:使用#if#elseif#else来控制条件判断。
  • 循环语句:使用#foreach来进行循环迭代。
  • 宏定义:使用#macro来定义可重用的宏。
  • 注释:使用##进行单行注释。

上下文数据

在代码生成过程中,若依会准备上下文数据,用于传递给Velocity模板引擎。上下文数据通常包括表信息、字段信息和其他生成参数等。这些数据被封装在一个context对象中,可以使用context.put(key, value)方法将数据添加到上下文中。

在模板中,可以通过${key}的形式引用上下文中的数据。例如,${table.name}表示引用上下文中表名的值。

information_schema

MySQL数据库中的information_schema数据库是MySQL的系统数据库之一,它包含了关于数据库、表、列等元数据信息的表。在代码生成器中,正是利用了information_schema数据库中的TABLES表和COLUMNS表来获取数据库表的信息,从而实现代码的生成。

  1. TABLES表:
    TABLES表存储了数据库中所有表的信息,包括表名、表所属的数据库、表的引擎类型、创建时间、更新时间等。通过查询TABLES表,代码生成器可以获取到需要生成代码的表的相关信息,如表名、表所在的数据库等。

  2. COLUMNS表:
    COLUMNS表存储了数据库中所有表的列信息,包括列名、数据类型、列的默认值、是否允许为空、字符集等。通过查询COLUMNS表,代码生成器可以获取到需要生成代码的表的列信息,如列名、数据类型等。

通过查询TABLES表和COLUMNS表,代码生成器可以获得数据库表的设计信息,包括表名、列名、数据类型等。这些信息可以用于生成代码文件,例如生成实体类的属性、Mapper接口的方法等。通过结合模板引擎,将这些数据库表的设计信息嵌入到模板中,就可以自动生成具体的Java代码文件。

代码生成器利用information_schema数据库中的TABLES表和COLUMNS表,提供了一种便捷的方式来获取数据库表的结构信息,使得生成的代码与数据库表的设计保持一致,减少了手动编写代码的工作量,并提高了代码的一致性和可维护性。

源码解析

在ruoyi-vue项目的ruoyi-generator模块中,代码生成器相关的代码实现了以下步骤。
通过以下步骤,ruoyi-vue代码生成器可以根据数据库表的结构信息和模板文件,生成具体的代码文件。导入表结构步骤将表和列信息存储到数据库中,生成代码步骤则利用这些信息和模板进行代码的生成和打包。这样可以实现代码的快速生成和下载,提高开发效率。

导入表结构(com.ruoyi.generator.controller.GenController#importTableSave接口)

@PreAuthorize("@ss.hasPermi('tool:gen:import')")
    @Log(title = "代码生成", businessType = BusinessType.IMPORT)
    @PostMapping("/importTable")
    public AjaxResult importTableSave(String tables)
    {
        String[] tableNames = Convert.toStrArray(tables);
        // 查询表信息
        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
        genTableService.importGenTable(tableList, SecurityUtils.getUserId());
        return AjaxResult.success();
    }
  • 通过查询information_schema数据库的tables表,获取目标表的表名、表注释、创建时间和更新时间。这里忽略了定时任务的表和已经生成过的表。
  • 初始化表数据,并将数据插入ruoyi数据库的gen_table表中。
  • 通过查询information_schema数据库的columns表,获取目标表的列信息,包括字段名、字段注释、字段类型、是否允许为null等详细信息。
  • 初始化列信息,并将数据插入ruoyi数据库的gen_table_column表中。

生成代码(com.ruoyi.generator.controller.GenController#batchGenCode接口)

@PreAuthorize("@ss.hasPermi('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);
    }
  • 从ruoyi数据库的gen_table表和gen_table_column表中查询出生成代码所需的表和列信息。
  • 初始化Velocity模板引擎。
  • 准备Velocity上下文信息,包括变量值信息。上下文中存储了从数据库查询到的表和列信息,以及其他生成参数。
  • 读取模板文件,渲染模板,并将渲染后的模板内容添加到压缩流中,最后生成zip压缩文件供前端下载。

generatorCoded方法

/**
     * 生成代码(自定义路径)
     *
     * @param tableName 表名称
     */
    @Override
    public void generatorCode(String tableName) {
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        Result result = getResult(table);
        for (String template : result.templates) {
            if (template.endsWith(".java.vm")) {
                result.context.put("fullPackage", getFullPackage(template));
            }
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(result.context, sw);
            String path = null;
            try {
                path = generatePath(template, table);
                File file = new File(path);
                FileUtils.writeStringToFile(file, sw.toString(), CharsetKit.UTF_8);
                log.info("{}", file.getAbsoluteFile());
            } catch (IOException e) {
                throw new ServiceException("渲染模板失败,表名:" + table.getTableName() + ", path: " + path);
            }
        }
    }

这段代码是在若依(Ruoyi)项目的代码生成器中的一个方法,用于生成代码并写入文件。

具体解释如下:

  1. 方法签名:
    public void generatorCode(String tableName)

    该方法接受一个参数 tableName,表示要生成代码的表名。

  2. 查询表信息:
    GenTable table = genTableMapper.selectGenTableByName(tableName);

    通过 genTableMapper(数据访问层)根据表名查询数据库中的表信息,并将结果保存在 GenTable 对象 table 中。

  3. 获取模板结果:
    Result result = getResult(table);

    通过调用 getResult 方法,根据查询到的表信息 table,获取生成代码所需的模板文件和上下文数据,结果保存在 Result 对象 result 中。

  4. 遍历模板文件:
    for (String template : result.templates)

    遍历 result 中的模板文件列表。

  5. 处理 Java 模板:

    if (template.endsWith(".java.vm")) {
        result.context.put("fullPackage", getFullPackage(template));
    }
    

    如果模板文件以 .java.vm 结尾,表示为 Java 类的模板文件。将生成的代码所属的包名(通过 getFullPackage 方法获取)放入上下文数据 result.context 中。

  6. 渲染模板:

    StringWriter sw = new StringWriter();
    Template tpl = Velocity.getTemplate(template, Constants.UTF8);
    tpl.merge(result.context, sw);
    

    使用 Velocity 模板引擎,根据模板文件和上下文数据,将模板渲染为具体的代码,结果保存在 StringWriter 对象 sw 中。

  7. 生成文件:

    String path = generatePath(template, table);
    File file = new File(path);
    FileUtils.writeStringToFile(file, sw.toString(), CharsetKit.UTF_8);
    

    根据模板文件和表信息,生成代码文件的路径。然后创建文件对象 file,将渲染后的代码内容写入文件中。

  8. 日志输出:
    log.info("{}", file.getAbsoluteFile());

    输出生成的代码文件的绝对路径。

  9. 异常处理:

    } catch (IOException e) {
        throw new ServiceException("渲染模板失败,表名:" + table.getTableName() + ", path: " + path);
    }
    

    如果在渲染模板和生成文件的过程中发生了异常,抛出自定义的 ServiceException 异常,并提供失败的表名和路径信息。

通过以上步骤,这段代码会根据表名查询表信息,获取模板文件和上下文数据,然后遍历模板文件,将模板渲染为具体的代码,最后生成代码文件并写入磁盘。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/582289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端技术搭建贪吃蛇小游戏(内含源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分 ✨ 写在前面 上周我们实通过前端基础实现了井字游戏&#xff0c;今天还是继续按照我们原定的节奏来带领大家完成一个贪吃蛇游戏&#xff0c;功能也比较简单简单&#xff0c;也…

第四章 Text

目录 TextFontsGlyphsFont TypesThe Font DictionaryEncodings Text StateFont and SizeRendering Mode Drawing TextPositioning TextWhat’s Next Text 在本章中&#xff0c;您将学习如何在页面上绘制文本。 绘图文本是 PDF 图形中最复杂的部分&#xff0c;但它也是帮助 PDF…

【Netty】Netty中的超时处理与心跳机制(十九)

文章目录 前言一、超时监测二、IdleStateHandler类三、ReadTimeoutHandler类四、WriteTimeoutHandler类五、实现心跳机制5.1. 定义心跳处理器5.2. 定义 ChannelInitializer5.3. 编写服务器5.4. 测试 结语 前言 回顾Netty系列文章&#xff1a; Netty 概述&#xff08;一&#…

太坑了,盘点BeanUtils.copyProperties的11个小坑

我们日常开发中&#xff0c;经常涉及到DO、DTO、VO对象属性拷贝赋值&#xff0c;很容易想到org.springframework.beans.BeanUtils的copyProperties 。它会自动通过反射机制获取源对象和目标对象的属性&#xff0c;并将对应的属性值进行复制。可以减少手动编写属性复制代码的工作…

“游蛇”大规模邮件攻击针对中国用户

近半年黑客团伙频频对我国实施攻击活动。研究人员发现&#xff0c;“游蛇”黑产团伙自2022年下半年开始至今&#xff0c;针对中国用户发起了大规模电子邮件攻击活动。 黑客使用电子邮件在内的多种传播方式。 该团伙利用钓鱼邮件、伪造的电子票据下载站、虚假应用程序下载站、…

eclipse固件库生成的操作流程

一.方法介绍 有时候我们需要将某个功能模块封装成一个库&#xff0c;只留出接口供别人使用&#xff0c;那么就需要打包处理&#xff0c;eclipse是如何操作的呢&#xff1f;本文仅仅讨论我所知道的两种方式&#xff0c;倘若还有更简便的方法也非常欢迎网友补充。 1.在已有的工…

【PyQt5】使用QtDesigner创建Splitter

目录 Splitter效果演示 目前在Qt Designer无法检索到QSplitter。 实现方式&#xff1a; 1.同时选中两个需要实现splitter样式的控件&#xff0c;以QTreeWidget和QTableWidget为例&#xff1b; 2.右击–>布局–>使用分裂器&#xff08;根据需求选择水平或垂直布局&#x…

Groovy系列二 Groovy GDK

目录 Groovy中自带集合方法 sort方法对集合排序 findAll 查询所有符合条件的元素 collect 返回 一个新的list inject 强大的累计功能 each、eachWithIndex find、findIndexOf 查询符合条件的数据 any判断符合条件的数据 every查询所有条件都满足的数据 reverse将集合…

linux下安装EclipseCDT:离线安装与在线安装

文章目录 前言&#xff1a;1. 离线下载1.1 下载EclipseCDT1.2 下载jdk1.3 安装jdk1.4 安装eclipse 2. 在线安装&#xff1a;2.1 安装jdk2.2 安装EclipseCDT2.2.1 简单安装2.2.2 ubuntu官方推荐安装方式2.2.3 apt安装(报错logo) 总结&#xff1a; 前言&#xff1a; Eclipse使用…

ChatGPT对软件测试的影响

本文首发于个人网站「BY林子」&#xff0c;转载请参考版权声明。 ChatGPT是一个经过预训练的AI语言模型&#xff0c;可以通过聊天的方式回答问题&#xff0c;或者与人闲聊。它能处理的是文本类的信息&#xff0c;输出也只能是文字。它从我们输入的信息中获取上下文&#xff0c;…

Spring 日志文件

日志 日志是程序的重要组成部分,日志可以:a.记录错误日志和警告日志(发现和定位问题)b.记录用户登录日志,方便分析用户是正常登录还是恶意破解用户c.记录系统的操作日志,方便数据恢复和定位操作人d.记录程序的执行时间,方便为以后优化程序提供数据支持 日志使用 SpringBoot …

东风/小米投资!去年EHB出货20万台,这家公司获科技进步一等奖

5月26日上午&#xff0c;2022年度上海市科学技术奖励大会在上海展览中心中央大厅召开&#xff0c;隆重表彰为国家、为上海科技事业和现代化建设作出突出贡献的科技工作者。同驭汽车与同济大学等单位联合申报的“汽车线控制动系统关键技术及产业化”项目获得科技进步奖项目一等奖…

【CCNP | 网络模拟器GNS系列】安装、配置和使用 GNS3

目录 1. 下载 GNS31.1 GitHub下载&#xff08;推荐&#xff09;1.2 官方下载&#xff08;示例&#xff09; 2. 安装GNS3&#xff08;1&#xff09;进入GNS3设置界面&#xff08;2&#xff09;许可协议&#xff08;3&#xff09;选择启动目录文件夹&#xff08;4&#xff09;选择…

ArcGIS中制作一张985、211院校分布图

一、数据来源及介绍 1.985、211院校名录 985、211院校名录主要来源于网络。 2.行政边界数据 行政边界数据来源于环境资源科学与数据中心&#xff08;中国科学院资源环境科学与数据中心 (resdc.cn)&#xff09;&#xff0c;该网站包含我们国家任何一个省市的行政边界&#xf…

2024考研408-计算机组成原理第二章-数据的表示

文章目录 一、数制与编码1.1、进位计数制1.1.1、计数方法&#xff08;最古老计数方法、十进制计数、r进制计数&#xff09;1.1.2、进制转换①任意进制转为十进制②二进制转八进制、十六进制③八进制、十六进制转二进制④十进制转任意进制&#xff08;包含整数、小数&#xff0c…

Python绘图神器Plotly安装、使用及导出图像教程

1. Plotly安装 Plotly 是一个快速完善并崛起的交互式的、开源的绘图库库&#xff0c;Python 库则是它的一个重要分支。现已支持超过40种独特的图表类型&#xff0c;涵盖了广泛的统计、金融、地理、科学和三维用例。 Python 中可以使用 pip 或者 conda 安装 Plotly&#xff1a…

使用校园账号登录WOS(Web of Science)并检索文献

使用校园账号登录WOS&#xff08;Web of Science&#xff09;并检索文献 写在最前面登录WOS检索文献文献检索文献检索结果分析文章类型&#xff08;Document Types&#xff09;发表年份&#xff08;Publication years&#xff09;期刊&#xff08;Publication/Source Titles&am…

chatgpt赋能python:Python中n个数相加–实现简单、计算准确

Python中n个数相加 – 实现简单、计算准确 Python是一门功能强大的编程语言&#xff0c;能够在各个领域得到广泛应用。在数据处理和科学领域&#xff0c;Python是最受欢迎的编程语言之一。在Python中&#xff0c;n个数相加是一种常见的操作&#xff0c;它可以在数据处理中做到…

计算机网络六 应用层

应用层 网络应用模型 客户/服务器模型(C/S) 客户/服务器模型是一种常见的网络应用模型。客户端是指与用户直接交互的计算机应用程序&#xff0c;服务器则是提供服务的计算机系统或应用程序。在客户/服务器模型中&#xff0c;客户端发送请求&#xff0c;服务器端回应请求。客户…

Redis7实战加面试题-高阶篇(案例落地实战bitmap/hyperloglog/GEO)

案例落地实战bitmap/hyperloglog/GEO 面试题&#xff1a; 抖音电商直播&#xff0c;主播介绍的商品有评论&#xff0c;1个商品对应了1系列的评论&#xff0c;排序展现取前10条记录 用户在手机App上的签到打卡信息:1天对应1系列用户的签到记录&#xff0c;新浪微博、钉钉打卡签…