若依代码生成器的使用

news2024/9/24 11:29:31

一、代码生成器的使用

1.新建maven模块

原则上,我们的业务代码和若依系统本身的系统代码是要做隔离的,一方面是易于之后随着若依系统升级而升级,另一方面则是纯粹的合理性考虑。

这里新建一个ruoyi-business模块作为业务代码模块,新建完ruoyi-business模块之后添加ruoyi-framework依赖,pom文件如下所示

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>ruoyi</artifactId><groupId>com.ruoyi</groupId><version>3.4.0</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.kdyzm</groupId><artifactId>ruoyi-business</artifactId><version>1.0.0-SNAPSHOT</version><dependencies><!-- 核心模块--><dependency><groupId>com.ruoyi</groupId><artifactId>ruoyi-framework</artifactId></dependency></dependencies></project>

之后在ruoyi-admin添加ruoyi-business模块的依赖

<dependency><groupId>com.kdyzm</groupId><artifactId>ruoyi-business</artifactId><version>1.0.0-SNAPSHOT</version></dependency>

2.准备代码生成器配置

ruoyi-vue系统中代码生成器相代码都在ruoyi-generator模块中,代码生成的配置在resources/generator.yml文件中,由于要在新的模块ruoyi-business中做开发,要有个新包名,包名取作com.kdyzm.business,所以generator.yml配置文件内容如下:

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

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

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

# MyBatis配置mybatis:# 搜索指定包别名typeAliasesPackage:com.ruoyi.**.domain,com.kdyzm.**.domain
  • 修改mybatis的mapper扫描包路径

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

@MapperScan({"com.ruoyi.**.mapper","com.kdyzm.**.mapper"})publicclassApplicationConfig{
    ...
}

最后,在ruoyi-admin新增一个Config类,扫描com.kdyzm包,以将ruoyi-business模块中的所有组件纳入spring管理。

package com.ruoyi.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author kdyzm
 */@Configuration@ComponentScan(basePackages = "com.kdyzm")publicclassConfig {
}

3.准备表

这里新建一张商品表作为示例,注意,这里的字段和表都要加上注释

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

4.生成代码

进入系统工具-代码生成页面,点击导入按钮,找到goods表并导入,如下图所示

然后点击生成代码按钮

之后,就可以得到一个ruoyi.zip压缩文件,压缩文件中包含生成的前后端代码以及sql语句文件,生成的代码目录结构如下所示

├── 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

二、将生成的代码应用到项目

1.后端代码

将生成代码中的main目录直接拷贝到ruoyi-business模块下的src目录,可以看到生成的代码是典型的三层架构,从controller到mapper都已经帮我们生成好了。

2.前端代码

前端代码对应着生成目录中的vue目录,这里将vue/api目录中的内容拷贝到ruoyi-ui/src/api目录中,将vue/views中的内容拷贝到ruoyi-ui/src/views目录,操作上,直接将生成的api和views目录拷贝到src目录即可。

3.sql代码

生成的sql代码是创建菜单和按钮权限使用的,直接在ruoyi数据库下执行 goodsMenu.sql 文件中的内容即可。

-- 菜单 SQLinsertinto sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('商品', '3', '1', 'goods', 'business/goods/index', 1, 0, 'C', '0', '0', 'business:goods:list', '#', 'admin', sysdate(), '', null, '商品菜单');

-- 按钮父菜单IDSELECT@parentId := LAST_INSERT_ID();

-- 按钮 SQLinsertinto sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('商品查询', @parentId, '1',  '#', '', 1, 0, 'F', '0', '0', 'business:goods:query',        '#', 'admin', sysdate(), '', null, '');

insertinto sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('商品新增', @parentId, '2',  '#', '', 1, 0, 'F', '0', '0', 'business:goods:add',          '#', 'admin', sysdate(), '', null, '');

insertinto sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('商品修改', @parentId, '3',  '#', '', 1, 0, 'F', '0', '0', 'business:goods:edit',         '#', 'admin', sysdate(), '', null, '');

insertinto sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('商品删除', @parentId, '4',  '#', '', 1, 0, 'F', '0', '0', 'business:goods:remove',       '#', 'admin', sysdate(), '', null, '');

insertinto sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('商品导出', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', 'business:goods:export',       '#', 'admin', sysdate(), '', null, '');

三、测试

重新运行前后端代码,打开系统工具菜单(为何在这里?这是若依vue的bug,已经提到gitee,bug链接: I3915P )的商品菜单

可以看到,前后端代码只是复制粘贴,后端接口、前端菜单、权限等等一切都已经被代码生成器帮我们做完了,可以说代码生成器极大的简化了我们的开发。

四、代码生成器高级使用

在三的测试过程中,我们发现,商品是否上架这个字段对应的前端表单是个文本输入框,但是实际上这里应该是个下拉列表框或者单选按钮才对,因为它只有两个值:0或者1,ruoyi-vue代码生成器实际上是支持这种操作的。之前生成代码的时候导入表之后直接点击了下载按钮生成了代码,实际上跳过了一个重要的步骤,那就是编辑代码生成选项。

点击编辑按钮之后,跳转修改生成配置页面。

在这个页面中,可以修改字段在前端的显示类型以及字典类型,比如,要想“商品是否上架”在前端展示为单选框,就可以修改显示类型为“单选框”,字典类型设置为“业务是否(需要新增数据字典,0表示下架,1表示上架)”。

提交之后重新生成的代码样式:

可以看到,商品是否字段变成了下拉列表和单选框的样式。

另外,若依代码生成器支持三种数据格式模板的代码生成:单表、树表、主子表,这里默认使用的是单表模板,也是最常使用的模板。

五、代码生成器原理

1.Velocity

Velocity是一个基于Java的模板引擎,其提供了一个Context容器,在java代码里面我们可以往容器中存值,然后在vm文件中使用特定的语法获取,这是velocity基本的用法,其与jsp、freemarker并称为三大视图展现技术。作为一个模块引擎,除了作为前后端分离的MVC展现层,Velocity还有一些其他用途,比如源代码生成。

在若依Vue系统中,正是使用了Velocity技术实现的源代码生成。大体上,源代码生成只需三步走:

  1. 创建模板文件

  1. 准备上下文(变量值)

  1. 替换模板文件中的变量

三步走完之后源代码就生成了,说起来是很简单的,但是实际上做起来会比较麻烦,特别是第一步创建模板文件是最复杂的,以下为index.vue模板文件部分源代码:

#foreach($column in $columns)
#if($column.query)
#set($dictType=$column.dictType)
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.htmlType == "input")
...

可以看到,该vue模板文件中充斥着大量Velocity的if-else语法,嵌套在一起更是显得无比复杂。

总之,整体上来看,java代码的模板比较简单,vue和mybatis mapper的模板文件比较复杂。

2.information_schema 数据库

mysql数据库中有一个information_schema数据库,它是mysql的系统数据库之一,它里面存储着两个表TABLES以及COLUMNS,这两个表分别存储着所有的表信息以及所有表中的列信息,代码生成器正是以两张表的信息为核心实现的。

3.ruoyi-vue代码生成器源码分析

ruoyi-vue代码生成器相关代码均位于ruoyi-generator模块中,根据之前的实际操作体验上来看,最简单的情况,前端页面只需要两步即可完成代码生成

  • 导入表结构

  • 生成代码

实际上这两步对应着后端的两个接口:com.ruoyi.generator.controller.GenController#importTableSavecom.ruoyi.generator.controller.GenController#batchGenCode ,生成源码的步骤就要从这两步下手。

首先看com.ruoyi.generator.controller.GenController#importTableSave 接口,它做了以下这些事情

  1. 从information_schema数据库的tables表中查询目标表的表明、标注释、创建时间和更新时间,但是忽略掉定时任务的表和已经生成过的表。

  1. 初始化表数据并将数据插入ruoyi数据库的gen_table表

  1. 从information_schema数据库的columns表中查询目标表的列信息,包含字段名、字段注释、字段类型、是否允许为null等详细信息

  1. 初始化列信息并将数据插入ruoyi数据库的gen_table_column表

接下来看下 com.ruoyi.generator.controller.GenController#batchGenCode 接口,它做了以下这些事情

  1. 从ruoyi数据库的gen_table、gen_table_column表查询出生成代码需要的表和列信息。

  1. 初始化Velocity

  1. 准备Velocity上下文信息(变量值信息)

  1. 读取模板、渲染模板,然后将渲染后的模板内容添加进如压缩流,之后前端就可以下载zip压缩文件了。

完毕。

六、扩展篇:封装独立版ruoyi-vue代码生成器

1.为什么要做这个

作为一个后端开发,我最经常做的事情不是搞啥系统架构,而是最简单的CRUD。。。若是能有一个代码一键生成工具自动根据已经创建的表信息生成CRUD后端代码,那岂不是能节省老鼻子功夫了——若依系统已经实现了这个代码生成器的工具,但是它依赖于前端页面,必须有权限访问“系统工具-代码生成”菜单才行,而这在企业中像我这种普通研发往往是是没有权限访问的。但是我有权限访问表,查看表结构。作为一个有追求的开发,既不肯开口问别人要权限,还想要实现代码生成器,该怎么做?

自己搞一个呗。

在这里封装的代码生成器不考虑前端页面调整功能,其实现的功能更加注重于后端代码,其作用和“系统工具-代码生成”页面中最简单的生成代码的两步(导入表和下载代码,无编辑)结果等效。

2.抽离ruoyi-vue代码生成器逻辑

ruoyi-vue中的ruoyi-generator模块有着完整的代码生成逻辑,但是它依托于ruoyi-admin的spring-boot框架才能运行,现在我要将ruoyi-generator模块的功能独立于spring-boot,让其作为一个普通的spring的程序,只有一个普通的main方法,实现和原来等效的功能。

这里的做法是直接修改ruoyi-generator模块,删除spring-boot的相关功能,但是保留spring、mybatis、druid等基础组件的依赖,然后将这些组件手动重新纳入spring容器中进行管理,最后通过main方法调用到相关模块。

具体就不展开讲了,有兴趣的可以看看我的源代码:https://gitee.com/kdyzm/ruoyi-vue-gen

3.独立版代码生成器使用方法

3.1 配置application.properties配置文件

该配置文件的内容如下:

mysql.username=${dbUserName}mysql.password=${dbPassword}mysql.connectionUrl=${dbUrl}mysql.driverClass=${dbDriverClassName}gen.author=kdyzmgen.packageName=com.kdyzm.businessgen.autoRemovePre=falsegen.tableName=newsgen.tablePrefix=sys_

上半部分是数据库配置,连接的是ruoyi-vue数据库,正常配置即可;下半部分是生成配置,除了gen.tableName,其它配置和原ruoyi-vue代码生成器的配置相同。

要注意,代码生成结果仅使用用ruoyi-vue项目,如需自定义模板,需要修改源代码。

3.2 打包和运行

在项目根目录运行命令mvn clean package,打包完成之后切换到target目录,使用命令java -jar ruoyi-vue-gen-1.0-SNAPSHOT.jar运行jar包得到ruoyi.zip压缩文件

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

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

相关文章

Mac环境安装python

一、介绍&#xff1a; Python是跨平台的&#xff0c;它可以运行在Windows、Mac和各种Linux/Unix系统上。在Windows上写Python程序&#xff0c;放到Linux上也是能够运行的。 要开始学习Python编程&#xff0c;首先就得把Python安装到你的电脑里。安装后&#xff0c;你会得到Pyt…

LearnOpenGL-光照-4.光照贴图

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject 文章目录光照贴图漫反射贴图例子1镜面光贴图例子2 采样镜面光贴图小结什么是光照贴图光照贴图如何影响颜色光…

开源一个通用的 HTTP 请求前端组件

像 Postman 这样可视化的 HTTP 请求工具是调试 API 不可或缺的利器。Postman 虽好但也越来越重&#xff0c;而且如果要整合到其他工具中&#xff0c;显然 Postman 又不是一个可行的方案。于是我想打造一个简单的前端组件&#xff08;widget&#xff09;&#xff0c;它是一个标准…

天池 DeepRec CTR 模型性能优化大赛 - 夺冠技术分享

作者&#xff1a;niceperf 团队 (李扬, 郭琳) 大家好&#xff0c;我们是 niceperf 团队&#xff0c;在天池 DeepRec CTR 模型性能优化大赛中&#xff0c;很荣幸取得了冠军的成绩 (Top 1/3802)。这篇文章复盘一下我们的参赛经验&#xff0c;希望对大家有所启发。 1.背景介绍 …

KDZD5035系列电缆试验油杯

一、概述 武汉凯迪正大总结十多年的局放试验经验&#xff0c;开发生产了KDZD5035系列电缆试验油杯终端&#xff0c;具有使用方便&#xff0c;性能可靠&#xff0c;本身局放量小等优点&#xff0c;与早期落地式油杯相比&#xff0c;可为用户节约大量的试验成本。 KDZD5520交流…

单片机学习笔记之点阵(8x8)

心血来潮&#xff0c;想捡一下丢了很久的单片机&#xff0c;纪录一下单片机学习简单的点阵显示&#xff0c;及踩到的䟘&#xff0c;找到吃灰很久的普中科技开发板&#xff08;非广告&#xff0c;为毕设学习买的&#xff09;。 1. 使用工具 使用开发板&#xff1a; 普中科技开发…

Hive---自定义函数

Hive自定义函数 文章目录Hive自定义函数定义自定义函数步骤创建一个Maven工程&#xff0c;导入依赖创建自定义函数类在 hive 的命令行窗口创建函数创建临时函数创建永久函数UDF打成 jar 包上传到服务器/opt/soft/hive312/lib/目录下将 jar 包添加到 hive 的 classpath建临时函数…

python数据类型与数据结构

目录 一、数据类型 1.1变量与常量 1.1.1变量 1.1.2常量 1.2字符串类型 1.3整数与浮点数 1.4List列表 1.5 元组tuple 1.6字典dict 二、字符串格式化 三、数据输入和类型转换 四、简单列表习题练习 一、数据类型 变量类型&#xff1a; 整数int&#xff08;4字节&#x…

IR-825 Biotin,IR 825 Biotin,IR825 Biotin,IR-825可以进行修饰生物素基团

IR825 Biotin&#xff0c;IR 825 Biotin&#xff0c;IR-825 Biotin | 生物素IR825荧光染料&#xff0c; 荧光染料IR825生物素&#xff0c;IR-825近红外染料 | CAS&#xff1a;N/A | 纯度&#xff1a;95%1.IR825 Biotin试剂信息&#xff1a;CAS&#xff1a;N/A外观&#xff1a;固…

字符串的使用

数组字符串转换 joinToString列表转成字符串 val str list.joinToString(",")split(“,”)字符串转成列表 val list1 str.split(",")subString()字符串截取 substring(0,2)这个只含开头不含结尾&#xff0c;索引从0开始 substring(2)这个表示截掉前两…

Genymotion模拟器安装

1.本节引言 如果你符合下述三种情况的话,你可以考虑安装一个Genymotion Android模拟器: 没有真机调试,只能用模拟器 嫌SDK内置的AVD启动速度,运行速度慢 电脑配置还可以,最好4G内存以上 如果你满足上述三种情况的话,那么装个比真机还快的Genymotion吧! 官方给出的介绍:…

Go爬虫学习笔记

N002.02 Go分布式爬虫实战 开篇 学习三阶段 入门&#xff0c;照猫画虎底层&#xff0c;了解方方面面&#xff0c;深入阅读源码和书籍借助开源组件来进行复杂设计&#xff0c;窥探各个组件赋能业务 分布式系统&#xff1a; 扩展性一致性可用性高并发微服务 爬虫&#xff1…

Java8使用Lambda表达式(流式)快速实现List转map 、分组、过滤等操作

利用java8新特性&#xff0c;可以用简洁高效的代码来实现一些数据处理。1 数据准备1.1 定义1个Fruit对象package com.wkf.workrecord.work;import org.junit.Test;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;/*** author wuKeFan* date …

Framework源码面试——Handler与事件传递机制面试集合

Handler面试题 Handler的作用&#xff1a; 当我们需要在子线程处理耗时的操作&#xff08;例如访问网络&#xff0c;数据库的操作&#xff09;&#xff0c;而当耗时的操作完成后&#xff0c;需要更新UI&#xff0c;这就需要使用Handler来处理&#xff0c;因为子线程不能做更新…

软件回归测试是什么?

一、软件回归测试是什么? 软件回归测试作为软件生命周期的一个组成部分&#xff0c;在整个软件测试过程中占有很大的工作量比重&#xff0c;软件开发的各个阶段都会进行多次回归测试。回归测试是指修改了旧代码后&#xff0c;重新进行测试以确认修改没有引入新的错误或导致其…

Boosting三巨头:XGBoost、LightGBM和CatBoost(发展、原理、区别和联系,附代码和案例)

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Binder ——binder的jni注册和binder驱动

环境&#xff1a;Android 11源码Android 11 内核源码源码阅读器 sublime textbinder的jni方法注册zygote启动1-1、启动zygote进程zygote是由init进程通过解析init.zygote.rc文件而创建的&#xff0c;zygote所对应的可执行程序是app_process&#xff0c;所对应的源文件是app_mai…

因果推断12--dragonnet论文和代码学习

目录 论文 dragonnet 1介绍 2 Dragonnet 3定向正则化 4相关工作 5实验 6讨论 NN-Based的模型 dragonnet 如何更新参数 dragonnet的损失函数 CausalML Dragonnet类 论文代码 论文 dragonnet Adapting Neural Networks for the Estimation of Treatment Effects 应…

二叉搜索树的实现

什么是二叉搜索树1.若它的左子树不为空&#xff0c;那么左子树上所有节点都小于根节点2.若它的右子树不为空&#xff0c;那么右子树上所有节点都小于根节点3.它的左右子树也分别是二叉搜索树4.使用中序遍历结果是从小到大定义节点&#xff0c;使用静态内部类static class TreeN…

http组成及状态及参数传递

http组成及状态及参数传递 早期的网页都是通过后端渲染来完成的&#xff1a;服务器端渲染&#xff08;SSR&#xff0c;server side render&#xff09;&#xff1a; 客户端发出请求 -> 服务端接收请求并返回相应HTML文档 -> 页面刷新&#xff0c;客户端加载新的HTML文档&…