MyBatis-Plus忽略多租戶隔離自定義注解
微服務(wù)項(xiàng)目中由于默認(rèn)開啟了租戶隔離,但是有些情況下需要個(gè)別方法不啟用。
為了實(shí)現(xiàn)這個(gè)目標(biāo)自定義了一個(gè)忽略租戶隔離的注解:
@IgnoreTenant
將他加在方法上即可,例如:
@IgnoreTenant
public CrmSmsTemplate getTemplateByCodeAndTenandtId(String code, Integer tenantId) {
return crmSmsTemplateMapper.selectOne(new QueryWrapper<CrmSmsTemplate>().eq("code", code).eq("tenant_id", tenantId));
}實(shí)現(xiàn)步驟:
1.首先定義MybatisPlus的配置類創(chuàng)建一個(gè)攔截器MybatisPlusInterceptor
將MybatisPlusSaasConfig中的mybatisPlusInterceptor方法修改
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
String tenantId = TenantContext.getTenant();
//如果通過線程獲取租戶ID為空,則通過當(dāng)前請求的request獲取租戶(shiro排除攔截器的請求會(huì)獲取不到租戶ID)
if(oConvertUtils.isEmpty(tenantId)){
try {
tenantId = TokenUtils.getTenantIdByRequest(SpringContextUtils.getHttpServletRequest());
} catch (Exception e) {
//e.printStackTrace();
}
}
if(oConvertUtils.isEmpty(tenantId)){
tenantId = "0";
}
return new LongValue(tenantId);
}
@Override
public String getTenantIdColumn(){
return TenantConstant.TENANT_ID_TABLE;
}
// 返回 true 表示不走租戶邏輯
@Override
public boolean ignoreTable(String tableName) {
for(String temp: TENANT_TABLE){
if(temp.equalsIgnoreCase(tableName)){
if (Objects.nonNull(MybatisTenantContext.get())){
return MybatisTenantContext.get();
}
return false;
}
}
return true;
}
/*@Override
public boolean ignoreTable(String tableName) {
if (Objects.nonNull(MybatisTenantContext.get())){
return MybatisTenantContext.get();
}
return true;
}*/
}));
//update-begin-author:zyf date:20220425 for:【VUEN-606】注入動(dòng)態(tài)表名適配攔截器解決多表名問題
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor());
//update-end-author:zyf date:20220425 for:【VUEN-606】注入動(dòng)態(tài)表名適配攔截器解決多表名問題
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
//【jeecg-boot/issues/3847】增加@Version樂觀鎖支持
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}2,定義一個(gè)ThreadLocal本地線程變量 MybatisTenantContext用于維護(hù)是否開啟租戶隔離變量
package org.jeecg.config.mybatis;
public class MybatisTenantContext {
private static final ThreadLocal<Boolean> TENANT_CONTEXT_THREAD_LOCAL = new ThreadLocal<>();
public static Boolean get() {
return TENANT_CONTEXT_THREAD_LOCAL.get();
}
public static void set(boolean isIgnore){
TENANT_CONTEXT_THREAD_LOCAL.set(isIgnore);
}
public static void clear(){
TENANT_CONTEXT_THREAD_LOCAL.remove();
}
}3.自定義注解
package org.jeecg.config.filter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface IgnoreTenant {
/**
* true為不做租戶隔離 false為做租戶隔離
* @return
*/
boolean isIgnore() default true;
}4.注解切面類
ps:如果方法或者類上有其他注解用到租戶隔離的,如:日志注解,字典翻譯注解在point.proceed()后執(zhí)行邏輯。需要注意切面類的執(zhí)行順序,一定要保證TenantIgnoreAspect 先執(zhí)行,不然其它注解還是會(huì)有租戶隔離的情況??梢栽赥enantIgnoreAspect 切面類加上@Order(Integer.MIN_VALUE)注解 保證執(zhí)行順序
package org.jeecg.config.filter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.config.mybatis.MybatisTenantContext;
import org.jeecg.config.sign.util.BodyReaderHttpServletRequestWrapper;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;
@Aspect
@Slf4j
@Component
@Order(Integer.MIN_VALUE)
public class TenantIgnoreAspect {
/**
* 切入點(diǎn)
*/
@Pointcut("@within(org.jeecg.config.filter.IgnoreTenant) ||@annotation(org.jeecg.config.filter.IgnoreTenant)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
try {
Class<?> targetClass = point.getTarget().getClass();
IgnoreTenant classIgnoreTenant = targetClass.getAnnotation(IgnoreTenant.class);
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
IgnoreTenant methodIgnoreTenant = method.getAnnotation(IgnoreTenant.class);
//判斷類上是否有注解
boolean isClassAnnotated = AnnotationUtils.isAnnotationDeclaredLocally(IgnoreTenant.class, targetClass);
//判斷方法上是否有注解
boolean isMethodAnnotated = Objects.nonNull(methodIgnoreTenant);
//如果類上有
if (isClassAnnotated) {
MybatisTenantContext.set(classIgnoreTenant.isIgnore());
}
//如果方法上有 以方法上的為主
if (isMethodAnnotated) {
MybatisTenantContext.set(methodIgnoreTenant.isIgnore());
}
Object result = point.proceed();
return result;
} finally {
MybatisTenantContext.clear();
}
}
}到此為止就可以使用注解:@IgnoreTenant
補(bǔ)充:如果一個(gè)方法中有多個(gè)查詢,但是只有特定查詢需要忽略租戶隔離,可以使用下面的方式
@Service
public class DemoService {
public List<String> demoList(String name){
try {
MybatisTenantContext.set(true);
this.listByName(name);
return this.list();
}finally {
MybatisTenantContext.clear();
}
}
}
以上代碼是手動(dòng)維護(hù)本地線程變量 MybatisTenantContext,不可以使用注解,使用完一定要記得clear。更多相關(guān)MyBatis-Plus忽略多租戶隔離內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
EventBus與Spring Event區(qū)別詳解(EventBus 事件機(jī)制,Spring Event事件機(jī)制)
這篇文章主要介紹了EventBus與Spring Event區(qū)別,需要的朋友可以參考下2020-02-02
SpringBoot 引?MybatisGenerator的實(shí)現(xiàn)步驟
本文主要介紹了SpringBoot 引?MybatisGenerator的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼
在我們?nèi)粘i_發(fā)過程中,通常會(huì)涉及到數(shù)據(jù)權(quán)限問題,本文主要介紹了Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Java 關(guān)鍵字static詳解及實(shí)例代碼
這篇文章主要介紹了Java 關(guān)鍵字static詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04
Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel的操作方法
在做一個(gè)?SpringBoot?前后端分離項(xiàng)目的時(shí)候,需要將數(shù)據(jù)存到?Excel中,用戶可以下載?Excel,具體實(shí)現(xiàn)是采用?Apache?強(qiáng)大的?POI,本文給大家介紹Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel相關(guān)知識(shí),感興趣的朋友一起看看吧2023-09-09

