概述
当前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<?>)



















