尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

如何添加“默认给Sql查询语句加上租户条件”的功能

如何添加“默认给Sql查询语句加上租户条件”的功能
📅 发布时间:2026/6/19 23:06:26

从零实现“默认给 SQL 查询语句加上租户条件”的功能,本质上是利用MyBatis Plus的插件机制配合ThreadLocal上下文来实现的。

我们需要构建一条完整的“数据 -> 规则 -> 执行”的链路。以下是标准化的5 步实现指南:


第一步:准备“背包” (定义上下文容器)

你需要一个地方在当前线程中存储“当前租户是谁”。

代码核心:利用ThreadLocal。

publicclassTenantContextHolder{// 存放当前租户IDprivatestaticfinalThreadLocal<Long>TENANT_ID=newTransmittableThreadLocal<>();publicstaticvoidsetTenantId(LongtenantId){TENANT_ID.set(tenantId);}publicstaticLonggetTenantId(){returnTENANT_ID.get();}publicstaticvoidclear(){TENANT_ID.remove();}}

第二步:制定“规则” (实现 Handler 接口)

你需要告诉 MyBatis Plus 具体的过滤逻辑:租户ID是多少?列名叫什么?哪些表不需要加?

代码核心:实现TenantLineHandler接口。

@ComponentpublicclassMyTenantLineHandlerimplementsTenantLineHandler{// 1. 告诉 MP,当前租户ID是多少 (从背包里拿)@OverridepublicExpressiongetTenantId(){LongtenantId=TenantContextHolder.getTenantId();// 如果没拿到ID(比如没登录),返回 NullValue 可能会导致报错或查不到数据// 通常这里会做判空或者返回默认值returnnewLongValue(tenantId);}// 2. 告诉 MP,数据库里租户列的名字叫什么@OverridepublicStringgetTenantIdColumn(){return"tenant_id";}// 3. 告诉 MP,哪些表需要忽略 (白名单)@OverridepublicbooleanignoreTable(StringtableName){// A. 全局白名单:系统表(字典、菜单)不需要隔离if("sys_dict".equals(tableName)||"sys_menu".equals(tableName)){returntrue;}// B. 动态白名单:配合 @TenantIgnore 注解使用if(TenantContextHolder.isIgnore()){returntrue;}// 默认:必须加过滤条件returnfalse;}}

第三步:组装“引擎” (配置 MyBatis 拦截器)

有了规则(Handler),你需要把它交给执行者(Interceptor),并把执行者放入 MyBatis 的插件链中。

代码核心:配置MybatisPlusInterceptorBean。

@ConfigurationpublicclassMybatisConfig{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(MyTenantLineHandlertenantLineHandler){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();// 核心动作:创建租户拦截器,并注入上面的规则 Handler// ⚠️注意:建议放在分页插件之前interceptor.addInnerInterceptor(newTenantLineInnerInterceptor(tenantLineHandler));// 添加分页插件interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));returninterceptor;}}

第四步:数据“注入” (配置 Web 过滤器)

引擎装好了,但还得有人把燃料(租户ID)塞进第一步的“背包”里。通常是在请求刚进来时处理。

代码核心:实现Filter或HandlerInterceptor。

@ComponentpublicclassTenantContextFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain){try{// 1. 从请求头 Header 获取 tenant-idHttpServletRequestreq=(HttpServletRequest)request;StringtenantIdStr=req.getHeader("tenant-id");if(tenantIdStr!=null){// 2. 塞进 ThreadLocal 背包TenantContextHolder.setTenantId(Long.valueOf(tenantIdStr));}// 3. 放行,执行后续业务逻辑 (Service -> Mapper -> SQL拦截器)chain.doFilter(request,response);}finally{// 4. 【重要】请求结束,清空背包,防止线程污染TenantContextHolder.clear();}}}

🌟 总结:这一套下来发生了什么?

  1. 请求进来:Filter 从 Header 拿到tenant_id=1,存入TenantContextHolder。
  2. 业务查询:你写了userMapper.selectList(null)。
  3. 拦截改写:TenantLineInnerInterceptor拦截 SQL,调用MyTenantLineHandler。
  4. 读取规则:Handler 从TenantContextHolder拿到1。
  5. SQL 变身:SQL 被自动拼接为SELECT * FROM user WHERE tenant_id = 1。
  6. 请求结束:Filter 清空TenantContextHolder。

这就是实现“全自动多租户隔离”的完整标准流程。

相关新闻

  • EmotiVoice模型微调指南:针对特定领域优化语音表现
  • 【心电图信号处理】心电图信号处理(含基础波形检测、信号去噪、信号重建指标)【含Matlab源码 14715期】
  • EmotiVoice语音合成服务高并发架构设计

最新新闻

  • 2026年口碑好的白市驿亲子烧烤游玩/重庆亲子户外休闲/重庆亲子研学基地/重庆农耕体验亲子农家乐哪家值得去 - 行业平台推荐
  • 2026永康全屋定制口碑爆棚的真相
  • YOLO越界行为识别数据集:聚焦周界防护的实战型安防训练资源
  • 2026年可靠的液压防爆预警套管/光伏逆变器自卷套管/双层异色自卷纺织套管/尼龙自卷套管高口碑品牌推荐 - 行业平台推荐
  • 2026年优秀的pvc管/安徽pvc管/安徽pvc化工管/pvc排水管横向对比厂家推荐 - 行业平台推荐
  • 如何用Python一键下载网易云音乐完整歌单并保留元数据?

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号