当前位置: 首页 > news >正文

mybatisplus多租户原理略解

概述

当前mybatisPlus版本

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version>
</dependency>

jdk版本:17
springboot版本:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>3.1.2</version>
</dependency>

业务中想按照租户划分权限时,一般简单的就是在表里加个字段,但是这样每个sql语句都要改造,很不方便。

mybatisplus有个现成的租户插件
com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor
在配置租户插件之前,需要在token中先塞入租户id,方便后面在拦截器中获取当前用户的租户.

租户注入的关键代码在
com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor#buildTableExpression
在这里插入图片描述

配置

配置的时候租户拦截器需要放在第一个,即`index=0

package org.qps.common.tenant.handle;import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import org.qps.common.core.utils.StringUtils;
import org.qps.common.satoken.utils.LoginHelper;
import org.qps.common.tenant.helper.TenantHelper;
import org.qps.common.tenant.properties.TenantProperties;
import lombok.AllArgsConstructor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.StringValue;import java.util.List;/*** 自定义租户处理器**/
@AllArgsConstructor
public class PlusTenantLineHandler implements TenantLineHandler {private final TenantProperties tenantProperties;@Overridepublic Expression getTenantId() {String tenantId = LoginHelper.getTenantId();if (StringUtils.isBlank(tenantId)) {return new NullValue();}String dynamicTenantId = TenantHelper.getDynamic();if (StringUtils.isNotBlank(dynamicTenantId)) {// 返回动态租户return new StringValue(dynamicTenantId);}// 返回固定租户return new StringValue(tenantId);}@Overridepublic boolean ignoreTable(String tableName) {String tenantId = LoginHelper.getTenantId();// 判断是否有租户if (StringUtils.isNotBlank(tenantId)) {// 不需要过滤租户的表List<String> excludes = tenantProperties.getExcludes();// 非业务表List<String> tables = ListUtil.toList("gen_table","gen_table_column");tables.addAll(excludes);return tables.contains(tableName);}return true;}}package org.qps.common.tenant.config;import cn.dev33.satoken.dao.SaTokenDao;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.qps.common.core.utils.reflect.ReflectUtils;
import org.qps.common.mybatis.config.MybatisPlusConfig;
import org.qps.common.redis.config.RedisConfig;
import org.qps.common.redis.config.properties.RedissonProperties;
import org.qps.common.tenant.core.TenantSaTokenDao;
import org.qps.common.tenant.handle.PlusTenantLineHandler;
import org.qps.common.tenant.handle.TenantKeyPrefixHandler;
import org.qps.common.tenant.manager.TenantSpringCacheManager;
import org.qps.common.tenant.properties.TenantProperties;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.SingleServerConfig;
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;import java.util.ArrayList;
import java.util.List;/*** 租户配置类** TenantProperties 自定义租户配置对象* MybatisPlusConfig 自定义mybatisPlus配置,维护了分页拦截器等基础拦截器*/
@EnableConfigurationProperties(TenantProperties.class)
@AutoConfiguration(after = {MybatisPlusConfig.class})
@ConditionalOnProperty(value = "tenant.enable", havingValue = "true")
public class TenantConfig {/*** 初始化租户配置*/@Beanpublic boolean tenantInit(MybatisPlusInterceptor mybatisPlusInterceptor,TenantProperties tenantProperties) {List<InnerInterceptor> interceptors = new ArrayList<>();// 多租户插件 必须放到第一位interceptors.add(tenantLineInnerInterceptor(tenantProperties));interceptors.addAll(mybatisPlusInterceptor.getInterceptors());mybatisPlusInterceptor.setInterceptors(interceptors);return true;}/*** 多租户插件*/public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) {return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties));}}

多租户拦截忽略

启用多租户之后,有些业务sql想查询多个租户的数据或者不想被注入租户id。

那么可以加上com.baomidou.mybatisplus.annotation.InterceptorIgnore
@InterceptorIgnore(tenantLine = "true")
即可忽略

原理可以参考源码
com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor#beforeQuery

com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper#willIgnoreTenantLine

com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper#willIgnore

将注解数据初始化到内存中
com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper#initSqlParserInfoCache(java.lang.Class<?>)

相关文章:

mybatisplus多租户原理略解

概述 当前mybatisPlus版本 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version> </dependency>jdk版本&#xff1a;17 springboot版本&#xff1a;…...

Spring整合RabbitMQ-配制文件方式-1-消息生产者

Spring-amqp是对AMQP的一些概念的一些抽象&#xff0c;Spring-rabbit是对RabbitMQ操作的封装实现。 主要有几个核心类RabbitAdmin、RabbitTemplate、SimpleMessageListenerContainer等 RabbitAdmin类完成对Exchange、Queue、Binding的操作&#xff0c;在容器中管理 了RabbitA…...

Python Opencv实践 - 凸包检测(ConvexHull)

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/stars.png") plt.imshow(img[:,:,::-1])img_contour img.copy() #得到灰度图做Canny边缘检测 img_gray cv.cvtColor(img_contour, cv.COLOR_BGR2GRAY) edges…...

IP网络广播系统有哪些优点

IP网络广播系统有哪些优点 IP网络广播系统有哪些优点&#xff1f; IP网络广播系统是基于 TCP/IP 协议的公共广播系统&#xff0c;采用 IP 局域网或 广域网作为数据传输平台&#xff0c;扩展了公共广播系统的应用范围。随着局域网络和 网络的发展 , 使网络广播的普及变为可能 …...

【LeetCode】83. 删除排序链表中的重复元素

83. 删除排序链表中的重复元素&#xff08;简单&#xff09; 方法&#xff1a;一次遍历 思路 由于给定的链表是排好序的&#xff0c;因此重复的元素在链表中出现的位置是连续的&#xff0c;因此我们只需要对链表进行一次遍历&#xff0c;就可以删除重复的元素。 从指针 cur 指…...

【大数据】Flink 详解(七):源码篇 Ⅱ

本系列包含&#xff1a; 【大数据】Flink 详解&#xff08;一&#xff09;&#xff1a;基础篇【大数据】Flink 详解&#xff08;二&#xff09;&#xff1a;核心篇 Ⅰ【大数据】Flink 详解&#xff08;三&#xff09;&#xff1a;核心篇 Ⅱ【大数据】Flink 详解&#xff08;四…...

stable diffusion实践操作-SD原理

系列文章目录 本文专门开一节写SD原理相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 文章目录 系列文章目录前言一、原理说明1.1、出图原理1.1.1 AI画画不是和人一样&#xff0c;从0开始&#xff0c;而是一个去噪点的过程&am…...

C++ Primer Plus第十三章编程练习答案

1&#xff0c;以下面的类声明为基础: // base class class Cd{ // represents a CD disk private: char performers[50] ; char label[20]; int selections;// number of selections double playtime; // playing time in minutes public: Cd(char * sl,char * s2,int n,double…...

Elasticsearch:wildcard - 通配符搜索

Elasticsearch 是一个分布式、免费和开放的搜索和分析引擎&#xff0c;适用于所有类型的数据&#xff0c;例如文本、数字、地理空间、结构化和非结构化数据。 它基于 Apache Lucene 构建&#xff0c;Apache Lucene 是一个全文搜索引擎&#xff0c;可用于各种编程语言。 由于其速…...

配置类安全问题学习小结

目录 一、前言 二、漏洞类型 目录 一、前言 二、漏洞类型 2.1 Strict Transport Security Not Enforced 2.2 SSL Certificate Cannot Be Trusted 2.3 SSL Anonymous Cipher Suites Supported 2.4 "Referrer Policy”Security 头值不安全 2.5 “Content-Security-…...

IMX6ULL移植篇-uboot源码目录

一. uboot 源码分析前提 由于 uboot 会使用到一些经过编译才会生成的文件&#xff0c;因此&#xff0c;我们在分析 uboot的时候&#xff0c;需要先编译一下 uboot 源码工程。 这里所用的开发板是 nand-flash版本。 二. uboot 源码目录及编译 1. uboot 源码目录 uboot源码目…...

SAP MM学习笔记27- 购买依赖(采购申请)

前面已经努力的学习了 购买发注&#xff0c;入库&#xff0c;请求书照合 等功能&#xff0c;还是蛮多内容的哈。 剩下的功能&#xff0c;比如 右侧的 所要量决定&#xff0c;供给元决定&#xff0c;仕入先选择 还没学。 从这章开始&#xff0c;要开始学习它们了。 这一章先来…...

C++零碎记录(八)

14. 运算符重载简介 14.1 运算符重载简介 ① 运算符重载&#xff1a;对已有的运算符重新进行定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型。 ② 对于内置的数据类型的表达式的运算符是不可能改变的。 14.2 加号运算符重载 ① 加号运算符作用&#x…...

基于matlab的扩频解扩误码率完整程序分享

clc; clear; close all; warning off; addpath(genpath(pwd)); r5; N2^r-1;%周期31 aones(1,r); mzeros(1,N); for i1:(2^r-1) temp mod((a(5)a(2)),2); for jr:-1:2 a(j)a(j-1); end a(1)temp; m(i)a(r); end mm*2-1;%双极性码 %产生随…...

算法:轮转数组---循环取模运算

1、题目&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 2、分析特点&#xff1a; 轮转 > 取模运算 我们可以使用额外的数组来将每个元素放至正确的位置。用 n 表示数组的长度&#xff0c;我们遍历原数组&a…...

Vue教程

官网vue快速上手 vue示例图 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 代码&#xff1a;LearnVue...

算法之双指针题型:

双指针例题小总结&#xff1a; 力扣27&#xff1a; 移除元素 力扣题目链接 双指针分为&#xff1a; 快慢双指针&#xff1a;同一个起点&#xff0c;同向出发 相向双指针&#xff1a;从两端出发&#xff0c;方向相反&#xff0c;终会相遇 经典的双指针&#xff08;快慢双指…...

vue传递给后端时间格式问题

前端处理 首先前端使用moment.js进行处理 data.userEnrolDate moment(data.userEnrolDate).format(YYYY-MM-DD HH:mm:ss);后端处理 JsonFormat(timezone "GMT8", pattern "yyyy-MM-dd HH:mm:ss") DateTimeFormat(pattern "yyyy-MM-dd HH:mm:ss…...

php使用jwt作登录验证

1 在项目根目录下&#xff0c;安装jwt composer require firebase/php-jwt 2 在登录控制器中加入生成token的代码 use Firebase\JWT\JWT; use Firebase\JWT\Key; class Login extends Cross {/*** 显示资源列表** return \think\Response*/public function index(Request $r…...

【zlm】 PTS DTS

在音视频编码和传输中&#xff0c;PTS&#xff08;Presentation Time Stamp&#xff09;和DTS&#xff08;Decoding Time Stamp&#xff09;是两个关键的时间戳&#xff0c;用于确保音视频帧的顺序和同步。它们在多媒体处理中扮演重要的角色&#xff1a; PTS&#xff08;Presen…...

知识获取受限?5款开源工具助你合法解锁付费内容

知识获取受限&#xff1f;5款开源工具助你合法解锁付费内容 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 你是否曾在学术研究关键时刻被期刊付费墙阻挡&#xff1f;是否因新闻网站的…...

Cursor AI Pro终极解锁指南:告别试用限制的专业解决方案

Cursor AI Pro终极解锁指南&#xff1a;告别试用限制的专业解决方案 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your t…...

高性能无线基带FPGA实现:开源802.11 WiFi实时信号处理架构解析

高性能无线基带FPGA实现&#xff1a;开源802.11 WiFi实时信号处理架构解析 【免费下载链接】openwifi open-source IEEE 802.11 WiFi baseband FPGA (chip) design: driver, software 项目地址: https://gitcode.com/gh_mirrors/op/openwifi Openwifi是一个基于软件定义…...

NoSleep防休眠工具:系统唤醒与持续运行的高效解决方案

NoSleep防休眠工具&#xff1a;系统唤醒与持续运行的高效解决方案 【免费下载链接】NoSleep Lightweight Windows utility to prevent screen locking 项目地址: https://gitcode.com/gh_mirrors/nos/NoSleep 在数字化工作环境中&#xff0c;电脑意外休眠往往导致工作中…...

如何高效使用猫抓插件:浏览器资源嗅探实用指南

如何高效使用猫抓插件&#xff1a;浏览器资源嗅探实用指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字化时代&#xff0c;我们每天浏览网…...

SuperSplat部署完全指南:从开发到生产环境的终极教程

SuperSplat部署完全指南&#xff1a;从开发到生产环境的终极教程 【免费下载链接】super-splat 3D Gaussian Splat Editor 项目地址: https://gitcode.com/gh_mirrors/su/super-splat SuperSplat是一款基于Web的免费开源3D高斯泼溅编辑器&#xff0c;专为检查、编辑、优…...

食品批发厂家口碑推荐榜

在食品批发行业&#xff0c;选择一家口碑良好的厂家至关重要。优质的食品批发厂家不仅能提供高品质的产品&#xff0c;还能保障稳定的供应和良好的售后服务。今天&#xff0c;我们就来为大家推荐一些口碑出众的食品批发厂家&#xff0c;其中惠州市佳德旺食品有限公司表现尤为突…...

Stable Yogi Leather-Dress-Collection效果展示:2.5D视角下皮衣动态褶皱与身体贴合度真实感

Stable Yogi Leather-Dress-Collection效果展示&#xff1a;2.5D视角下皮衣动态褶皱与身体贴合度真实感 想象一下&#xff0c;你是一位动漫角色设计师&#xff0c;需要为角色设计一套充满质感的皮衣。传统的流程需要你手绘线稿、上色、刻画光影和褶皱&#xff0c;整个过程耗时…...

intv_ai_mk11开源可部署实践:支持Webhook回调,可对接企业微信/钉钉/飞书通知

intv_ai_mk11开源可部署实践&#xff1a;支持Webhook回调&#xff0c;可对接企业微信/钉钉/飞书通知 1. 项目概述 intv_ai_mk11是一款基于Llama架构的AI对话机器人&#xff0c;拥有7B参数规模&#xff0c;能够运行在GPU服务器上。这个开源项目不仅提供了强大的对话能力&#…...

语言的边界,与软件的命运

. GIF文件结构 相比于 WAV 文件的简单粗暴&#xff0c;GIF 的结构要精密得多&#xff0c;因为它天生是为了网络传输而设计的&#xff08;包含了压缩机制&#xff09;。 当我们用二进制视角观察 GIF 时&#xff0c;它是由一个个 数据块&#xff08;Block&#xff09; 组成的&…...