ruoyi-vue-pro 开发指南 ruoyi-vue-pro 开发指南
  • 萌新必读
  • 后端手册
  • 中间件手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
  • 运维手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
微服务版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读
  • 后端手册
  • 中间件手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
  • 运维手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
微服务版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读

    • 简介
    • 交流群
    • 视频教程
    • 功能列表
    • 快速启动(后端项目)
    • 快速启动(前端项目)
    • 接口文档
    • 技术选型
    • 项目结构
    • 代码热加载
    • 一键改包
    • 迁移模块(适合新项目)
    • 删除功能(以租户为例)
      • 👍 相关视频教程
      • 删除「多租户」功能
        • 第一步,删除菜单
        • 第二步,删除数据库表
        • 第三步,删除后端代码
        • 第四步,删除前端代码
        • 第五步,测试验收
      • 更多...
    • 表结构变更(版本升级)
    • 国产信创数据库(DM 达梦、大金、OpenGauss、瀚高)
    • 如何去除 Redis 缓存
    • 内网穿透
    • 面试题、简历模版、简历优化
    • 项目外包
  • 后端手册

    • 新建模块
    • 代码生成【单表】(新增功能)
    • 代码生成【主子表】
    • 代码生成(树表)
    • 代码生成(移动端)
    • 功能权限
    • 数据权限
    • 用户体系
    • 三方登录
    • OAuth 2.0(SSO 单点登录)
    • SaaS 多租户【字段隔离】
    • SaaS 多租户【数据库隔离】
    • WebSocket 实时通信
    • 异常处理(错误码)
    • 参数校验、时间传参
    • 分页实现
    • VO 对象转换、数据翻译
    • 文件存储(上传下载)
    • Excel 导入导出
    • 操作日志、访问日志、异常日志
    • MyBatis 数据库
    • MyBatis 联表&分页查询
    • 多数据源(读写分离)、事务
    • Redis 缓存
    • 本地缓存
    • 异步任务
    • 分布式锁
    • 幂等性(防重复提交)
    • 请求限流(RateLimiter)
    • HTTP 接口签名(防篡改)
    • HTTP 接口加解密
    • 单元测试
    • 验证码
    • 工具类 Util
    • 配置管理
    • 数据库文档
  • 中间件手册

    • 定时任务
    • 消息队列(内存)
    • 消息队列(Redis)
    • 消息队列(RocketMQ)
    • 消息队列(RabbitMQ)
    • 消息队列(Kafka)
    • 限流熔断
  • 工作流手册

    • 工作流演示
    • 功能开启
    • 工作流(达梦适配)
    • 审批接入(流程表单)
    • 审批接入(业务表单)
    • 流程设计器(BPMN)
    • 流程设计器(钉钉、飞书)
    • 选择审批人、发起人自选
    • 会签、或签、依次审批
    • 流程发起、取消、重新发起
    • 审批通过、不通过、驳回
    • 审批加签、减签
    • 审批转办、委派、抄送
    • 执行监听器、任务监听器
    • 流程表达式
    • 流程审批通知
    • 移动端审批
  • 大屏手册

    • 报表设计器
    • 大屏设计器
  • 支付手册

    • 功能开启
    • 支付宝支付接入
    • 微信公众号支付接入
    • 微信小程序支付接入
    • 支付宝、微信退款接入
    • 支付宝转账接入
    • 微信转账接入
    • 钱包充值、支付、退款
    • 模拟支付、退款
  • 会员手册

    • 功能开启
    • 微信公众号登录
    • 微信小程序登录
    • 微信小程序订阅消息
    • 微信小程序码
    • 会员用户、标签、分组
    • 会员等级、积分、签到
  • 商城手册

    • 商城演示
    • 功能开启
    • 商城装修
    • 在线客服
    • 【商品】商品分类
    • 【商品】商品属性
    • 【商品】商品 SPU 与 SKU
    • 【商品】商品评价
    • 【交易】购物车
    • 【交易】交易订单
    • 【交易】售后退款
    • 【交易】快递发货
    • 【交易】门店自提
    • 【交易】分销返佣
    • 【营销】优惠劵
    • 【营销】积分商城
    • 【营销】拼团活动
    • 【营销】秒杀活动
    • 【营销】砍价活动
    • 【营销】满减送活动
    • 【营销】限时折扣
    • 【营销】内容管理
    • 【统计】会员、商品、交易统计
  • ERP手册

    • ERP 演示
    • 功能开启
    • 【产品】产品信息、分类、单位
    • 【库存】产品库存、库存明细
    • 【库存】其它入库、其它出库
    • 【库存】库存调拨、库存盘点
    • 【采购】采购订单、入库、退货
    • 【销售】销售订单、出库、退货
    • 【财务】采购付款、销售收款
  • CRM手册

    • CRM 演示
    • 功能开启
    • 【线索】线索管理
    • 【客户】客户管理、公海客户
    • 【商机】商机管理、商机状态
    • 【合同】合同管理、合同提醒
    • 【回款】回款管理、回款计划
    • 【产品】产品管理、产品分类
    • 【通用】数据权限
    • 【通用】跟进记录、待办事项
  • AI大模型手册

    • AI 大模型演示
    • 功能开启
    • AI 聊天对话
    • AI 绘画创作
    • AI 知识库(RAG)
    • AI 音乐创作
    • AI 写作助手
    • AI 思维导图
    • AI 工具(function calling)
    • AI 工作流
    • Dify 工作流
    • FastGPT 工作流
    • Coze 智能体
    • 推理模式(thinking)
    • 联网搜索
    • MCP Client 客户端
    • MCP Server 服务端
    • 【模型接入】Claude
    • 【模型接入】OpenAI
    • 【模型接入】通义千问
    • 【模型接入】DeepSeek
    • 【模型接入】字节豆包
    • 【模型接入】腾讯混元
    • 【模型接入】硅基流动
    • 【模型接入】MiniMax
    • 【模型接入】月之月面
    • 【模型接入】百川智能
    • 【模型接入】文心一言
    • 【模型接入】LLAMA
    • 【模型接入】智谱 GLM
    • 【模型接入】讯飞星火
    • 【模型接入】微软 OpenAI
    • 【模型接入】谷歌 Gemini
    • 【模型接入】Stable Diffusion
    • 【模型接入】Midjourney
    • 【模型接入】Suno
  • IoT物联网手册

    • 功能开启
    • 产品管理
    • 设备管理
    • 物模型配置
    • 设备网关与子设备
    • 设备动态注册
    • 设备接入(概述)
    • 设备接入(HTTP 协议)
    • 设备接入(MQTT 协议)
    • 设备接入(EMQX 协议)
    • 设备接入(TCP 协议)
    • 设备接入(UDP 协议)
    • 设备接入(WebSocket 协议)
    • 设备接入(CoAP 协议)
    • 设备接入(Modbus Client 模式)
    • 设备接入(Modbus Server 模式)
    • 设备接入(自定义协议)
    • 场景联动
    • 数据流转
    • 告警配置
    • OTA 固件升级
  • MES手册

    • MES 演示
    • 功能开启
    • 【基础】物料产品、分类、计量单位
    • 【基础】客户管理、供应商管理
    • 【基础】车间设置、工作站设置
    • 【基础】编码规则
    • 【生产】工序设置、工艺流程
    • 【生产】生产工单
    • 【生产】生产排产、工序流转卡
    • 【生产】生产报工
    • 【生产】安灯配置、安灯呼叫
    • 【生产】工作记录
    • 【仓库】仓库与库区库位、条码赋码、SN码
    • 【仓库】批次管理、库存现有量、库存事务
    • 【仓库】到货通知、采购入库、采购退货
    • 【仓库】生产领料、生产退料、物料消耗
    • 【仓库】产品产出、产品入库
    • 【仓库】发货通知、销售出库、销售退货
    • 【仓库】外协发料、外协入库
    • 【仓库】其他入库、其他出库
    • 【仓库】调拨单、装箱管理
    • 【仓库】库存盘点
    • 【质量】检测项设置、常见缺陷
    • 【质量】质检方案
    • 【质量】来料检验(IQC)
    • 【质量】过程检验(IPQC)
    • 【质量】出货检验(OQC)
    • 【质量】退货检验(RQC)
    • 【质量】待检任务、检验结果、缺陷记录
    • 【设备】设备类型、设备台账
    • 【设备】点检保养项目、点检保养方案
    • 【设备】点检记录、保养记录、维修单
    • 【工具】工具类型、工装夹具台账
    • 【排班】班组设置、节假日设置
    • 【排班】排班计划、排班日历
  • WMS手册

    • WMS 演示
    • 功能开启
    • 【基础】仓库
    • 【基础】商品、SKU、分类、品牌
    • 【基础】往来企业(供应商、客户)
    • 【库存】库存记录、流水、统计
    • 【单据】入库
    • 【单据】出库
    • 【单据】移库
    • 【单据】盘库
    • 【其它】WMS、MES、ERP 对比
  • IM即时通讯手册

    • IM 演示
    • 功能开启
    • 【好友】好友关系、好友申请
    • 【群聊】群组、群成员、入群申请
    • 【消息】私聊、群聊、频道消息
    • 【频道】频道、频道素材
    • 【内容】表情、敏感词
    • 【通话】语音通话、视频通话、共享屏幕
    • 【WebSocket】实时推送与离线消息
  • 公众号手册

    • 功能开启
    • 公众号接入
    • 公众号粉丝
    • 公众号标签
    • 公众号消息
    • 模版消息
    • 自动回复
    • 公众号菜单
    • 公众号素材
    • 公众号图文
    • 公众号统计
  • 系统手册

    • 短信配置
    • 邮件配置
    • 站内信配置
    • Webhook(钉钉、飞书、企微)
    • 数据脱敏、字段权限
    • 敏感词
    • 地区 & IP 库
  • 运维手册

    • 开发环境
    • Linux 部署
    • Docker 部署
    • Jenkins 部署
    • 宝塔部署
    • 1Panel 部署
    • HTTPS 证书
    • 服务监控
    • Tomcat WAR 部署
  • 前端手册 Vue 3.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • CRUD 组件
    • 国际化
    • IDE 调试
    • 代码格式化
  • 前端手册 Vben 5.x

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • IDE 调试
    • 代码格式化
  • 前端手册 Vue 2.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
  • 前端手册 Admin Uniapp

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • IDE 调试
    • 代码格式化
    • 运行发布
  • 更新日志

    • 【v2026-06】
    • 【v2026-05】
    • 【v2026-04】
    • 【v2026-03】
    • 【v2026-01】
    • 【v2025-12】
    • 【v2025-11】
    • 【v2025-10】
    • 【v2025-09】
    • 【v2025-08】
    • 【v2-6-1】2025-07-19
    • 【v2-6-0】2025-06-07
    • 【v2.5.0】2025-05-13
    • 【v2.4.2】2025-04-12
    • 【v2.4.1】2025-02-09
    • 【v2.4.0】2024-12-31
    • 【v2.3.0】2024-10-07
    • 【v2.2.0】2024-08-02
    • 【v2.1.0】2024-05-05
    • 【v2.0.1】2024-03-01
    • 【v2.0.0】2024-01-26
  • 开发指南
  • 萌新必读
芋道源码
2022-10-17
目录

删除功能(以租户为例)

项目内置功能较多,会存在一些你可能用不到的功能。一般的情况下,建议通过设置该功能对应的菜单为【禁用】,实现功能的“删除”。如下图所示:

设置菜单为禁用

后续,如果你又需要使用到该功能,只需要设置该功能对应的菜单为【开启】即可。

🙂 当然,如果你希望彻底删除功能,那么就需要采用删除代码的方式。整个过程如下:

① 【菜单】第一步,使用管理后台的菜单管理,删除对应的菜单、按钮。
② 【数据库表】第二步,删除对应的数据库表。
③ 【后端代码】第三步,删除对应的 Controller、Service、数据库实体等后端代码;然后启动后端项目,若存在代码报错,则继续删除相关联的代码,之后如此反复,直到成功。
④ 【前端代码】第四步,删除对应的 View 和 API 等前端代码;然后启动前端项目,若存在代码报错,则继续删除相关联的代码,之后如此反复,直到成功。

🤖 推荐:借助 AI Agent 来删除功能

随着 AI Agent 的出现,删除功能这种“范围广、易遗漏”的体力活,非常适合交给 AI 来做。目前一般建议使用 Claude Code (opens new window)、Cursor (opens new window) 等 AI 编程工具来辅助生成代码。

推荐的协作方式是:

  1. 先让 AI 阅读项目,生成一份删除 plan(计划),或者沉淀为一个 skill(技能);
  2. 由你自己评审确认 plan / skill 是否正确、是否有遗漏或风险(尤其是会删到业务逻辑的地方);
  3. 确认无误后,再让 AI 按 plan / skill 执行删除,最后人工跑一遍编译与测试验收。

下面是一个使用 Kiro 为本项目生成的「删除多租户」skill 示例,可作为参考(你也可以基于它让 AI 生成其它功能的删除 skill):

点击展开:删除多租户的 skill 示例(SKILL.md)
---
name: delete-tenant
description: 删除 ruoyi-vue-pro(芋道)项目中的「多租户(SaaS Tenant)」功能。当用户希望移除多租户能力、不再需要 SaaS 字段隔离、想精简单租户部署,或提到“删除租户/去掉多租户/tenant 删除”时使用本技能。覆盖菜单、数据库表、后端代码、前端代码的完整删除步骤与验收。
---

# 删除「多租户」功能(以租户为例)

本技能指导如何从 ruoyi-vue-pro(芋道)项目中彻底删除多租户(SaaS Tenant)功能,
参考官方文档「删除功能(以租户为例)」https://doc.iocoder.cn/delete-code/ 的五步法,
并结合本仓库的真实结构做了落地说明。

> 重要:删除多租户是不可逆的破坏性操作,会影响数据库表、后端框架装配与前端页面。
> 执行前务必:
> 1. 在新分支上操作,先 `git status` 确认工作区干净;
> 2. 备份数据库(尤其是 `system_tenant`、`system_tenant_package` 及各业务表的 `tenant_id` 字段);
> 3. 与团队确认确实不再需要 SaaS 多租户隔离。
>
> 如果你只是想“临时关闭”多租户,不要删除代码,直接在 `yudao-server/src/main/resources/application.yaml`
> 中设置 `yudao.tenant.enable: false` 即可(见文末「替代方案」)。

整体顺序:**菜单 → 数据库表 → 后端代码 → 前端代码 → 测试验收**。

---

## 第一步:删除菜单

删除菜单是为了让前端不再显示「租户管理」「租户套餐」等入口。

涉及的菜单(`system_menu` 表,MySQL 种子数据见 `sql/mysql/ruoyi-vue-pro.sql`):

| 菜单 ID | 名称 | 权限标识 |
| --- | --- | --- |
| 1224 | 租户管理(目录) | - |
| 1138 | 租户列表 | - |
| 1139 | 租户查询 | system:tenant:query |
| 1140 | 租户创建 | system:tenant:create |
| 1141 | 租户更新 | system:tenant:update |
| 1142 | 租户删除 | system:tenant:delete |
| 1143 | 租户导出 | system:tenant:export |
| 1225 | 租户套餐 | - |
| 1226 | 租户套餐查询 | system:tenant-package:query |
| 1227 | 租户套餐创建 | system:tenant-package:create |
| 1228 | 租户套餐更新 | system:tenant-package:update |
| 1229 | 租户套餐删除 | system:tenant-package:delete |
| 5010 | 租户切换 | - |

操作方式(二选一):

- 推荐:在管理后台「系统管理 → 菜单管理」中,删除「租户管理」目录及其子菜单。
- 或直接在数据库执行(请同时同步 `sql/` 下你所用数据库方言的种子文件,避免重新初始化时菜单复活):

```sql
-- 删除运行库中的菜单(按需替换表前缀)
DELETE FROM system_menu WHERE id IN (1224, 1138, 1139, 1140, 1141, 1142, 1143, 1225, 1226, 1227, 1228, 1229, 5010);
-- 清理角色与菜单的关联
DELETE FROM system_role_menu WHERE menu_id IN (1224, 1138, 1139, 1140, 1141, 1142, 1143, 1225, 1226, 1227, 1228, 1229, 5010);
```

> 注意:`system_tenant_package` 的 `menu_ids` 字段中也会引用这些菜单 ID,删除套餐表后此引用自然失效,无需单独处理。

---

## 第二步:删除数据库表

删除租户相关的数据库表,并去除业务表中的多租户字段。

### 2.1 删除租户专属表

```sql
DROP TABLE IF EXISTS system_tenant;
DROP TABLE IF EXISTS system_tenant_package;
```

### 2.2 处理业务表的 tenant_id 字段(关键且影响最大)

多租户采用「字段隔离」:几乎所有业务表都带有 `tenant_id` 字段,由
`TenantDatabaseInterceptor` 自动拼接 `WHERE tenant_id = ?`。删除多租户后:

- 若**保留** `tenant_id` 字段:最省事,字段闲置不影响使用,推荐保留。
- 若**彻底删除** `tenant_id` 字段:需要对每张含该字段的表执行
  `ALTER TABLE xxx DROP COLUMN tenant_id;`。这一步范围极广、风险高,
  仅在确有必要时进行,且务必先备份。

> 建议:第一次删除多租户时**保留** `tenant_id` 字段,只删租户表 + 关闭框架逻辑。
> 这样最小化风险,后续确认无误再考虑清字段。

同步更新 `sql/` 目录下你所使用数据库方言的初始化脚本,移除 `system_tenant`、
`system_tenant_package` 两张表的建表与 INSERT 语句(涉及文件示例:
`sql/mysql/ruoyi-vue-pro.sql`、`sql/postgresql/ruoyi-vue-pro.sql`、
`sql/dm/ruoyi-vue-pro-dm8.sql`、`sql/kingbase/ruoyi-vue-pro.sql`、
`sql/opengauss/ruoyi-vue-pro.sql` 等)。

---

## 第三步:删除后端代码

后端分两部分:① 删除 `yudao-module-system` 中租户的业务代码;② 移除 `yudao-framework`
中的多租户框架 starter 及各模块对它的依赖。

### 3.1 删除 system 模块的租户业务代码

删除以下文件 / 目录(路径基于 `yudao-module-system/src/main/java/cn/iocoder/yudao/module/system`):

- `controller/admin/tenant/`(`TenantController`、`TenantPackageController` 及其 `vo/`)
- `controller/app/tenant/`(`AppTenantController` 及其 `vo/`)
- `service/tenant/`(`TenantService`、`TenantServiceImpl`、`TenantPackageService`、
  `TenantPackageServiceImpl`、`handler/TenantInfoHandler`、`handler/TenantMenuHandler`)
- `dal/dataobject/tenant/`(`TenantDO`、`TenantPackageDO`)
- `dal/mysql/tenant/`(`TenantMapper`、`TenantPackageMapper`)
- `convert/tenant/`(`TenantConvert`)
- `api/tenant/`(`TenantApiImpl`)

对应测试代码:`yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/tenant/`。

同时删除 `framework` 中对外暴露的租户 API 接口:
- `yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/tenant/TenantCommonApi.java`

> 删除后用全局搜索处理编译错误,重点检查对 `TenantApiImpl`、`TenantCommonApi`、
> `TenantService`、`TenantDO` 的引用,逐一移除或改写。

### 3.2 删除多租户框架 starter

删除整个模块目录:
- `yudao-framework/yudao-spring-boot-starter-biz-tenant/`

并从 `yudao-framework/pom.xml` 的 `<modules>` 中移除:
```xml
<module>yudao-spring-boot-starter-biz-tenant</module>
```

从 `yudao-dependencies/pom.xml` 中移除 `yudao-spring-boot-starter-biz-tenant` 的
`<dependencyManagement>` 声明。

### 3.3 移除各模块对租户 starter 的依赖

以下 `pom.xml` 都依赖了 `yudao-spring-boot-starter-biz-tenant`,逐个删除该 `<dependency>` 块:

- `yudao-module-system/pom.xml`
- `yudao-module-infra/pom.xml`
- `yudao-module-bpm/pom.xml`
- `yudao-module-crm/pom.xml`
- `yudao-module-pay/pom.xml`
- `yudao-module-member/pom.xml`
- `yudao-module-mp/pom.xml`
- `yudao-module-ai/pom.xml`
- `yudao-module-report/pom.xml`
- `yudao-module-iot/yudao-module-iot-biz/pom.xml`
- `yudao-module-mall/yudao-module-promotion/pom.xml`
- `yudao-module-mall/yudao-module-statistics/pom.xml`
- `yudao-module-mall/yudao-module-trade/pom.xml`
- `yudao-framework/yudao-spring-boot-starter-websocket/pom.xml`(`scope` 为 `provided`)

> 用 `grep -r "yudao-spring-boot-starter-biz-tenant" --include=pom.xml .` 复核,确保无遗漏。

### 3.4 清理框架特性的代码引用

删除 starter 后,全项目对以下类型的引用都会编译失败,需要逐处清理:

- `TenantContextHolder`(获取/设置当前租户)
- `TenantUtils.execute(...)` / `TenantUtils.executeIgnore(...)`(在指定/忽略租户上下文执行逻辑)
- `TenantUtils.addTenantHeader(...)`(RPC/HTTP 调用时注入 `tenant-id` 请求头)
- `@TenantIgnore`(忽略租户拦截的注解,类级/方法级/Mapper 方法级)
- `@TenantJob`(标记定时任务遍历所有租户执行)
- `TenantBaseDO`

#### ⚠️ 关键:`TenantUtils` 的删除——什么时候要保留里面的代码

`TenantUtils.execute(tenantId, () -> {...})`、`TenantUtils.executeIgnore(() -> {...})`
的参数是一个 `Runnable` / `Callable` **lambda,业务逻辑就写在 lambda 体里面**。
这类调用**绝对不能整段删掉**,否则会把真正的业务逻辑一起删除。正确做法是
**“拆壳保芯”:去掉 `TenantUtils.xxx(...)` 这层包装,保留 lambda 内部的代码**。

它的本质只是“临时切换/忽略租户上下文执行一段逻辑”。删除多租户后,这层上下文切换
不再需要,但里面的业务逻辑必须原样保留。

改写规则:

1. **`Runnable` 形式(无返回值)**——展开 lambda 体:

   ```java
   // 删除前
   TenantUtils.execute(tenant.getId(), () -> {
       Long roleId = createRole(tenantPackage);
       createUser(roleId, createReqVO);
   });

   // 删除后(去掉包装,保留内部逻辑)
   Long roleId = createRole(tenantPackage);
   createUser(roleId, createReqVO);
   ```

2. **`Callable` 形式(有返回值)**——把 lambda 里的 `return` 提到外层:

   ```java
   // 删除前
   TenantUtils.execute(refreshTokenDO.getTenantId(),
           () -> accessTokenDO.setUserInfo(buildUserInfo(userId, userType)));

   // 删除后
   accessTokenDO.setUserInfo(buildUserInfo(userId, userType));
   ```

   若内部依赖 `tenantId` 变量(如把它写入 DO),删除后该字段可直接去掉或保留默认值。

3. **`executeIgnore(...)`** 同理:它只是“忽略租户隔离执行一段查询/写入”,删除多租户后
   隔离本就不存在,直接保留内部逻辑即可。

4. **`addTenantHeader(headers, tenantId)`**——这是给 RPC/HTTP 请求注入 `tenant-id` 头,
   可整行删除(不含业务逻辑)。

> 排查方式:`grep -rn "TenantUtils" --include=*.java .` 逐处确认是 `execute/executeIgnore`
> (需拆壳保留内部逻辑)还是 `addTenantHeader`(可整行删除)。

#### `@TenantIgnore`

被很多 system 模块的 DO / Mapper 使用(如 `MenuDO`、`DictDataDO`、`DictTypeDO`、
`OAuth2ClientDO`、`SmsTemplateDO`、`MailTemplateDO`、`NotifyTemplateDO`,以及
`OAuth2AccessTokenMapper`、`OAuth2RefreshTokenMapper` 的方法级注解等)。
**只删注解本身,DO / Mapper 方法及其逻辑全部保留。**

#### `@TenantJob`

原本带该注解的 Job 会遍历所有租户各执行一次,删除注解后改为普通执行一次。
**只删注解,`execute(...)` 方法体保留。** 参考 `yudao-module-system/.../job/DemoJob.java`
及各模块定时任务。注意方法体里若用到 `TenantContextHolder.getTenantId()` 之类(如 DemoJob
的打印),需一并清理这些引用,但其余业务逻辑保留。

#### `TenantContextHolder`

读取/设置当前租户上下文的工具。删除多租户后相关读写都失去意义:
- 取值后仅用于赋给 `tenantId` 字段/变量的,连同该字段处理一起去掉;
- 取值后参与业务判断的(少见),需结合上下文改写为单租户语义,**不要盲删导致逻辑缺失**。

> 总原则:**框架包装(上下文切换、忽略隔离、注解、请求头注入)删掉,被包装的业务逻辑保留。**

### 3.5 清理配置

从 `yudao-server/src/main/resources/application.yaml` 中删除 `yudao.tenant` 整段配置:

```yaml
  tenant: # 多租户相关配置项
    enable: true
    ignore-urls: ...
    ignore-visit-urls: ...
    ignore-tables: ...
    ignore-caches: ...
```

同时检查多环境配置文件(`application-local.yaml`、`application-dev.yaml` 等)是否有同名片段。

---

## 第四步:删除前端代码

> 注意:本仓库的 `yudao-ui/yudao-ui-admin-vue3` 已被精简,租户相关前端文件可能不存在。
> 以下为标准前端(Vue3 / Vben / Vue2)中租户文件的常规位置,按你实际使用的前端工程处理。

Vue3(`yudao-ui-admin-vue3`):
- 删除视图目录:`src/views/system/tenant/`、`src/views/system/tenantPackage/`
- 删除 API:`src/api/system/tenant/`、`src/api/system/tenantPackage/`
- 删除登录页/请求中携带 `tenant-id`、租户切换相关逻辑(搜索 `tenant`、`tenantId`、
  `tenant-id`、`getTenantId`、`useTenantStore` 等关键字)
- 检查 `src/utils/request`、登录逻辑、`store` 中与租户相关的拦截/缓存

Vben(`yudao-ui-admin-vben`)、Vue2(`yudao-ui-admin-vue2`)类似:搜索 `tenant` 关键字,
删除对应 `views`、`api`、请求头注入与租户选择组件。

---

## 第五步:测试验收

1. 后端编译:在仓库根目录执行
   ```bash
   mvn -q -T 1C clean install -DskipTests
   ```
   确保无编译错误(重点是 `TenantXxx`、`@TenantIgnore`、`@TenantJob` 的残留引用)。
2. 启动 `yudao-server`,确认应用正常启动,无 `YudaoTenantAutoConfiguration` 相关报错。
3. 验证核心接口:登录、获取菜单、用户列表等可正常访问(不再要求携带 `tenant-id` 请求头)。
4. 前端启动后,确认菜单中无「租户管理 / 租户套餐」,相关页面与请求无报错。
5. 跑一遍关键单元测试(如保留测试框架)。
6. 全局复核:
   ```bash
   grep -rn "tenant" --include=*.java yudao-module-system yudao-framework | grep -iv "//"
   grep -rn "yudao-spring-boot-starter-biz-tenant" --include=pom.xml .
   ```

---

## 替代方案:只关闭不删除

如果目标只是「单租户运行」,强烈建议不要删代码,改为关闭开关:

```yaml
# yudao-server/src/main/resources/application.yaml
yudao:
  tenant:
    enable: false
```

`YudaoTenantAutoConfiguration` 上的 `@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable")`
会在 `enable=false` 时整体不装配多租户的 AOP / 拦截器 / 过滤器 / MQ / 缓存逻辑,
既保留了代码可回退性,又达到关闭多租户的效果。

提醒:AI 生成的删除方案不一定 100% 准确,务必人工评审。尤其要注意 TenantUtils 这类“包装类”——只删外层包装,里面的业务逻辑必须保留(详见下文第三步第 ⑨ 点)。

下面,我们来举一些例子。

# 👍 相关视频教程

  • 从零开始 07:如何有效的删除不用的功能? (opens new window)

# 删除「多租户」功能

  • 对应功能的文档:多租户
  • 对应的关键字是 tenant

# 第一步,删除菜单

删除“租户管理“下的所有菜单,从最里层的按钮开始。如下图所示:

删除“租户管理“菜单

# 第二步,删除数据库表

删除 system_tenant 和 system_tenant_package 表。如下图所示:

删除数据库表

# 第三步,删除后端代码

① 删除 yudao-module-system-api 模块的 api/tenant (opens new window) 包。

② 删除 yudao-module-system-api 模块的 ErrorCodeConstants (opens new window) 类中,和租户、租户套餐相关的错误码。如下图所示:

删除错误码

如果想删除的更干净,可以把 system_error_code 表中,对应编号的错误码也都删除一下。

③ 删除 yudao-module-system 模块的如下包:

  • api/tenant (opens new window)
  • controller/admin/tenant (opens new window)
  • service/tenant (opens new window)
  • test/service/tenant (opens new window)
  • dal/dataobject/tenant (opens new window)
  • dal/mysql/tenant (opens new window)
  • convert/tenant (opens new window)

④ 删除 yudao-spring-boot-starter-biz-tenant (opens new window) 模块。

然后,使用 IDEA 搜索 yudao-spring-boot-starter-biz-tenant 关键字,删除 Maven 中所有对它的定义与引用。如下图所示:

删除  使用

之后,使用 IDEA 刷新下 Maven 依赖。如下图所示:

租户-刷新Maven依赖

⑤ 运行 YudaoServerApplication 启动类,会报 cn.iocoder.yudao.framework.tenant.core.db 不存在的错误,需要将继承 TenantBaseDO 的数据库实体,都改成继承 BaseDO 基类。

租户-修改继承BaseDO类

⑥ 运行 YudaoServerApplication 启动类,会报 cn.iocoder.yudao.framework.tenant.core.aop 不存在的错误,需要去除对 @TenantIgnore 注解的使用。如下图所示:

租户-删除@TenantIgnore注解

⑦ 运行 YudaoServerApplication 启动类,会报 cn.iocoder.yudao.module.system.service.tenant 不存在的错误,需要去除对 TenantService 的使用。如下图所示:

租户-删除TenantService的使用

⑧ 运行 YudaoServerApplication 启动类,会报 cn.iocoder.yudao.framework.tenant.core.context 不存在的错误,需要去除对 TenantContextHolder 的使用。如下图所示:

租户-删除TenantContextHolder的使用

⑨ 删除使用 TenantUtils 调用的地方,只删除 TenantUtils 外层,里面的逻辑需要保留!!!

⑩ 运行 YudaoServerApplication 启动类,终于成功了!!!

ps:可以将 application.yaml 配置文件中,对应的 yudao.tenant 配置项给进一步删除。

# 第四步,删除前端代码

以 yudao-admin-ui 为示例~

① 删除 View 和 API 的前端代码:

  • views/system/tenant (opens new window)
  • views/system/tenantPackage (opens new window)
  • api/system/tenant.js (opens new window)
  • api/system/tenantPackage.js (opens new window)

② 在 yudao-admin-ui 目录下,执行 npm run local 成功。访问登录页,结果访问白屏。需要清理 login.vue 页,涉及 tenant 关键字的代码。例如说:

清理 login.vue 的代码

刷新,成功访问登录界面。

③ 在 yudao-admin-ui 目录下,搜索 tenant 或 Tenant 关键字,可进一步清理多租户的代码。例如说:

进一步清理前端代码

# 第五步,测试验收

至此,我们已经完成了多租户的代码删除,还是蛮艰辛的~

后续,你可以简单测试一下,看看是不是删除代码,导致一些小问题。

# 更多...

如果你有其它功能想要删除,可以在 Issue (opens new window) 留言,可以不断补充到该文档。

迁移模块(适合新项目)
表结构变更(版本升级)

← 迁移模块(适合新项目) 表结构变更(版本升级)→

Theme by Vdoing | Copyright © 2019-2026 芋道源码 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×