package com.artfess.base.handler; import com.artfess.base.conf.SaaSConfig; import com.artfess.base.constants.SQLConst; import com.artfess.base.constants.TenantConstant; import com.artfess.base.context.BaseContext; import com.artfess.base.feign.UCFeignService; import com.artfess.base.util.AppUtil; import com.artfess.base.util.BeanUtils; import com.artfess.base.util.ContextThread; import com.artfess.base.util.JsonUtil; import com.artfess.base.util.StringUtil; import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.jsonwebtoken.lang.Assert; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.NullValue; import net.sf.jsqlparser.expression.StringValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; /** * 多租户处理器 * * @author heyifan * @company 阿特菲斯信息技术有限公司 * @email heyf@jee-soft.cn * @date 2020年4月6日 */ @Component public class MultiTenantHandler implements TenantHandler, ContextThread { private final Logger log = LoggerFactory.getLogger(getClass()); /** * 多租户标识 */ private String tenantIdColumn = "tenant_id_"; /** * 需要过滤的表 */ private List ignoreTableNames = new ArrayList<>(); @Autowired private BaseContext apiContext; @Resource SaaSConfig saaSConfig; private static ThreadLocal threadLocalIgnore = new ThreadLocal(); /** * 线程变量 临时忽略 自动添加租户id的操作 */ public static MultiTenantIgnoreResult setThreadLocalIgnore() { threadLocalIgnore.set(true); return new MultiTenantIgnoreResult(); } public static Boolean getThreadLocalIgnore() { Boolean ignoreTable = threadLocalIgnore.get(); if (BeanUtils.isNotEmpty(ignoreTable) && ignoreTable) { return true; } return false; } public static void removeThreadLocalIgnore() { threadLocalIgnore.remove(); } /** * 租户Id * * @return */ @Override public Expression getTenantId(boolean where) { // 从当前系统上下文中取出当前请求的服务商ID,通过解析器注入到SQL中。 String tenantId = apiContext.getCurrentTenantId(); log.debug("当前租户为{}", tenantId); if (tenantId == null) { return new NullValue(); } return new StringValue(tenantId); } /** * 获取当前用户所属租户的租户CODE *
     * 如果当前是平台管理用户则返回null
     * 
* * @return */ public String getTenantCode() { // 租户模式下生成物理表时需要在表名中追加租户别名 if (saaSConfig.isEnable()) { String currentTenantId = apiContext.getCurrentTenantId(); // 非平台管理用户 if (!TenantConstant.PLATFORM_TENANT_ID.equals(currentTenantId)) { UCFeignService ucFeign = AppUtil.getBean(UCFeignService.class); JsonNode tenantManage = ucFeign.getTenantById(currentTenantId); Assert.notNull(tenantManage, "未获取到当前用户所属的租户信息"); String tenantCode = JsonUtil.getString((ObjectNode) tenantManage, "code"); Assert.isTrue(StringUtil.isNotEmpty(tenantCode), "租户中的租户别名为空"); return tenantCode; } } return null; } /** * 设置租户字段名 * * @param tenantId */ public void setTenantId(String tenantId) { this.tenantIdColumn = tenantId; } /** * 设置忽略的表名 * * @param list */ public void setIgnoreTableNames(List list) { this.ignoreTableNames = list; } /** * 获取忽略的表名列表 * * @return */ public List getIgnoreTableNames() { return this.ignoreTableNames; } /** * 租户字段名 * * @return */ @Override public String getTenantIdColumn() { return tenantIdColumn; } /** * 根据表名判断是否进行过滤 * 忽略掉一些表:如租户表(sys_tenant)本身不需要执行这样的处理 * * @param tableName * @return */ @Override public boolean doTableFilter(String tableName) { if (getThreadLocalIgnore()) { return true; } if (StringUtil.isNotEmpty(tableName) && tableName.toUpperCase().startsWith(SQLConst.CUSTOMER_TABLE_PREFIX)) { return true; } if (StringUtil.isNotEmpty(tableName) && tableName.toUpperCase().startsWith(SQLConst.MATRIX_TABLE_PREFIX)) { return true; } return ignoreTableNames.stream().anyMatch((e) -> e.equalsIgnoreCase(tableName)); } @Override public void cleanAll() { removeThreadLocalIgnore(); } }