赞
踩
当前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; @Override public 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); } @Override public 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 { /** * 初始化租户配置 */ @Bean public 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<?>)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。