若依的代碼生成模塊,是以數據庫中的表為基石,進行創建的。
新建數據庫表
(dig_workshop和dig_company):
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for dig_workshop
-- ----------------------------
DROP TABLE IF EXISTS `dig_workshop`;
CREATE TABLE `dig_workshop` (
`workshop_id` bigint NOT NULL AUTO_INCREMENT COMMENT '工作區/車間 ID',
`workshop_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '工作區/車間名稱',
`workshop_desc` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '描述',
`company_id` bigint DEFAULT NULL COMMENT '隸屬公司',
`background_img` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '背景圖',
`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '帳號狀態(0正常 1停用)',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '刪除標志(0代表存在 2代表刪除)',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '創建者',
`create_time` datetime DEFAULT NULL COMMENT '創建時間',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
PRIMARY KEY (`workshop_id`)
) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='工作區/車間主表';
-- ----------------------------
-- Records of dig_workshop
-- ----------------------------
INSERT INTO `dig_workshop` VALUES ('1', '未分配車間', '未分配默認值', '1', '', '0', '0', 'admin', '2021-11-10 11:06:14', '', null);
INSERT INTO `dig_workshop` VALUES ('100', '測控 - 北1樓', '聯康測控北邊1樓 車間', '4', '', '0', '0', 'admin', '2021-11-10 11:06:57', '', null);
INSERT INTO `dig_workshop` VALUES ('101', '測控 - 南1樓', '聯康測控南邊1樓 車間', '4', '', '0', '0', 'admin', '2021-11-10 11:07:31', '', null);
-- ----------------------------
-- Table structure for dig_company
-- ----------------------------
DROP TABLE IF EXISTS `dig_company`;
CREATE TABLE `dig_company` (
`company_id` bigint NOT NULL AUTO_INCREMENT COMMENT '公司ID',
`company_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '公司名稱',
`company_shortname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '公司簡稱',
`belong` tinyint(1) NOT NULL COMMENT '是否是本公司(1是,2不是)',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '創建者',
`create_time` datetime DEFAULT NULL COMMENT '創建時間',
`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '帳號狀態(0正常 1停用)',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '刪除標志(0代表存在 2代表刪除)',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
PRIMARY KEY (`company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='公司表';
-- ----------------------------
-- Records of dig_company
-- ----------------------------
INSERT INTO `dig_company` VALUES ('1', '江蘇聯康信息股份有限公司', '聯康信息', '1', 'admin', '2021-11-10 10:18:51', '0', '0', '', null);
INSERT INTO `dig_company` VALUES ('2', '深圳聯康測控有限公司', '深圳測控', '1', 'admin', '2021-11-10 10:19:29', '0', '0', '', null);
INSERT INTO `dig_company` VALUES ('3', '上海億克泰電子科技有限公司', '億克泰', '1', 'admin', '2021-11-10 10:19:51', '0', '0', '', null);
INSERT INTO `dig_company` VALUES ('4', '江蘇聯康測控有限公司', '江蘇測控', '1', 'admin', '2021-11-10 10:20:14', '0', '0', '', null);
啟動生成代碼模塊
導入表結構
在數據庫中創建的表,需要先導入。
設置代碼生成方式
點擊編輯按鈕,會出現基本信息,字段信息,生成信息,三個小的模塊。
基本信息
字段信息
其中,字段描述,是建表語句中每個字段的Comment
,同時它對應@excel注解中的描述信息,如:
/**工作區/車間名稱 */
@Excel(name = "工作區/車間名稱")
private String workshopName;
像我這樣寫的字段過長,再添加修改頁面會擠到一起,非常不美觀,所以數據庫建表的Comment盡量簡短一點。
或者在字段信息的生成列表中,進行手動修改。
物理類型是數據庫中的字段的類型,Java類型是要生成的代碼中的實體類的數據類型。
**java屬性,**是把列名去掉下划線,然后轉換大小寫后,寫入到實體類中的屬性名。
插入列里的勾選項,是點擊新增后,彈出的頁面中,顯示的列信息。
編輯列里的勾選項,是點擊修改后,彈出的頁面中,顯示的列信息。
列表列里的勾選項,是index頁面初始化后,展示的列信息。
查詢列里的勾選項,是在index頁面上方,顯示的查詢條件。
查詢方式 就是 = != > < like等查詢方式
必填,如果勾選的話,它會在vue文件的表單校驗中,增加一個判斷(文本框前面帶個紅*
)
其中 背景圖, background_img字段不是文本框,而是一個上傳圖片的控件,這個可以直接選。
status字段是一個單選框,它和 字典表中的
生成信息
生成模板,分為單表Crud,樹表crud,主子表crud。
生成的包路徑,是生成的代碼存放的路徑。
模塊名就不用說了。
業務名,是這個模塊下業務類的名稱,對應domain中的dto,而controller和service等也會根據其自動生成。
生成功能名,會出現在java類的description中,也會出現在@log注解中title里。
/** * 導出車間管理列表 */
@PreAuthorize(hasPermi = "digital:workshop:export")
@Log(title = "車間管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DigWorkshop digWorkshop) throws IOException
{
List<DigWorkshop> list = digWorkshopService.selectDigWorkshopList(digWorkshop);
ExcelUtil<DigWorkshop> util = new ExcelUtil<DigWorkshop>(DigWorkshop.class);
util.exportExcel(response, list, "車間管理數據");
}
生成方式選擇 zip 即可
我前面再數據庫中生成了兩張表,是因為dig_workshop和dig_company之間有關聯關系,通過外鍵company_id進行關聯。
再查詢dig_workshop這張表的時候,需要通過company_id關聯dig_company查詢出對應的company名稱,一並返回到前台。
如果模板采用主子表的Crud,那么必須要關聯表事先導入。
生成代碼
代碼生成后,是一個zip格式的文件夾,解壓后放到對應的模塊下即可。
它同時也生成了菜單的SQL語句
-- 菜單 SQL
insert into 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('車間管理', '2047', '1', 'workshop', 'digital/workshop/index', 1, 0, 'C', '0', '0', 'digital:workshop:list', '#', 'admin', sysdate(), '', null, '車間管理菜單');
-- 按鈕父菜單ID
SELECT @parentId := LAST_INSERT_ID();
-- 按鈕 SQL
insert into 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', 'digital:workshop:query', '#', 'admin', sysdate(), '', null, '');
insert into 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', 'digital:workshop:add', '#', 'admin', sysdate(), '', null, '');
insert into 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', 'digital:workshop:edit', '#', 'admin', sysdate(), '', null, '');
insert into 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', 'digital:workshop:remove', '#', 'admin', sysdate(), '', null, '');
insert into 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', 'digital:workshop:export', '#', 'admin', sysdate(), '', null, '');
直接扔到數據庫里運行即可。
運行完之后,車間管理的菜單就出來了,但是它是沒有圖標的,還需要手動添加一下。
配置文件
到這里,基本上這個模塊的簡單功能開發,已經接近尾聲。
但是,現在代碼跑起來,是無法成功運行的,因為yml文件還沒有配置。
bootstrap.yml
# Tomcat
server:
port: 9203
# Spring
spring:
application:
# 應用名稱
name: ruoyi-digital
profiles:
# 環境配置
active: dev
cloud:
nacos:
discovery:
# 服務注冊地址
server-addr: localhost:8848
# 開發環境與生產環境隔離(該配置是dev環境)
namespace: ecb178a8d-429147-91b49-60c2ee-77c2e876e95
config:
# 配置中心地址
server-addr: localhost:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 開發環境與生產環境隔離(該配置是dev環境)
namespace: ecb178a8d-429147-91b49-60c2ee-77c2e876e95
我采用的nacos作為配置中心,它讀取的默認格式為:
${prefix}:默認是spring.application.name的值,也就是 ruoyi-digital
${spring.profiles.active}我配的是dev,所以它的值是 dev
。我做的這個項目,配置文件是分離的,開發一套,生產一套,是根據命名空間進行划分的。
namespace: ecb178a8d-429147-91b49-60c2ee-77c2e876e95 就是 dev環境
${file-extension},我配的是 yml
因此我寫的這個功能模塊的配置文件格式為:ruoyi-digital-dev.yml
我的配置中心和注冊服務都是在dev環境中,通過namespace進行隔離。
ruoyi-digital-dev.yml
# spring配置
spring:
redis:
host: localhost
port: 6379
password:
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: 123456
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,slf4j
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
datasource:
# 主庫數據源
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: root
# 從庫數據源
# slave:
# username:
# password:
# url:
# driver-class-name:
# seata: true # 開啟seata代理,開啟后默認每個數據源都代理,如果某個不需要代理可單獨關閉
# seata配置
seata:
# 默認關閉,如需啟用spring.datasource.dynami.seata需要同時開啟
enabled: false
# Seata 應用編號,默認為 ${spring.application.name}
application-id: ${spring.application.name}
# Seata 事務組編號,用於 TC 集群名
tx-service-group: ${spring.application.name}-group
# 關閉自動代理
enable-auto-data-source-proxy: false
# 服務配置項
service:
# 虛擬組和分組的映射
vgroup-mapping:
ruoyi-system-group: default
config:
type: nacos
nacos:
serverAddr: 127.0.0.1:8848
group: SEATA_GROUP
namespace:
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
namespace:
# mybatis配置
mybatis:
# 搜索指定包別名
typeAliasesPackage: com.ruoyi.digital
# 配置mapper的掃描,找到所有的mapper.xml映射文件
mapperLocations: classpath:mapper/**/*.xml
# swagger配置
swagger:
title: 系統模塊接口文檔
license: Powered By ruoyi
licenseUrl: https://ruoyi.vip
這里面redis和數據庫都是連本地的環境,方便測試。
mybatis配置里,搜索的包名要和生成代碼中的包名對應
typeAliasesPackage: com.ruoyi.digital :掃描該路徑下的所有mapper文件
mapperLocations: classpath:mapper/**/*.xml :掃描類路徑下,目錄及其子目錄中所有以xml結尾的文件
配置文件寫好了,項目就可以啟動了,但是此時依然無法訪問。
因為網關還沒有配置。
配置網關
當項目啟動時,就已經在nacos中注冊了服務名稱。
之所以使用gateway網關,就是不想暴露IP地址和端口,僅通過服務名驚醒調用,讓網關根據匹配規則,進行請求的轉發
ruoyi-gateway-dev.yml
spring:
redis:
host: localhost
port: 6379
password:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 數字化模塊
- id: ruoyi-digital
uri: lb://ruoyi-digital
predicates:
- Path=/digital/**
filters:
- StripPrefix=1
StripPrefix=1 :是截取一位,然后進行匹配。比如當有個請求訪問 /digital/workshop/list
路徑的時候,它和網關中的ruoyi-digital
規則匹配上,它就會截取請求的前一位,然后再轉發到ruoyi-digital
模塊中去。
換言之,訪問/digital/workshop/list
,就相當於訪問 lb://ruoyi-digital/workshop/list
這樣配,真的好奇怪,為什么呢?
我覺得第一個原因,是若依的開源作者,想要抹除模塊之間的界限。
第二個原因,就是生成的代碼中也是這樣寫的,不這樣配不行啊,證據如下:
/** * 車間管理Controller * @date 2021-11-10 */
@RestController
@RequestMapping("/workshop")
public class DigWorkshopController extends BaseController
{// 業務代碼略}
請看它的 @RequestMapping
注解。
待完善
網關配置完成后,整個功能模塊就跑通了,這只是一個簡單的腳手架,有很多業務邏輯和公司業務沖突的地方,還需要更加細致的二次開發。
舉個栗子:
文件上的信息展示,明顯需要修改。
再比如,底邊欄的數據列表,不應該全是input文本框,應該有下拉框和按鈕的組合,還有字段的展示,也有待完善。
這只是舉得一個小功能里面得一些小瑕疵,像這樣得下次,自動生成得代碼里還有很多,
盡管如此,ruoyi自動生成代碼得功能依然非常強大,避免了程序重復造輪子得窘境。
最后說一句:
擁抱開源