MyBatis-Plus忽略多租戶(hù)隔離自定義注解
微服務(wù)項(xiàng)目中由于默認(rèn)開(kāi)啟了租戶(hù)隔離,但是有些情況下需要個(gè)別方法不啟用。
為了實(shí)現(xiàn)這個(gè)目標(biāo)自定義了一個(gè)忽略租戶(hù)隔離的注解:
@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的配置類(lèi)創(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(); //如果通過(guò)線程獲取租戶(hù)ID為空,則通過(guò)當(dāng)前請(qǐng)求的request獲取租戶(hù)(shiro排除攔截器的請(qǐng)求會(huì)獲取不到租戶(hù)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 表示不走租戶(hù)邏輯 @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)表名適配攔截器解決多表名問(wèn)題 interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor()); //update-end-author:zyf date:20220425 for:【VUEN-606】注入動(dòng)態(tài)表名適配攔截器解決多表名問(wèn)題 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); //【jeecg-boot/issues/3847】增加@Version樂(lè)觀鎖支持 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }
2,定義一個(gè)ThreadLocal本地線程變量 MybatisTenantContext用于維護(hù)是否開(kāi)啟租戶(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為不做租戶(hù)隔離 false為做租戶(hù)隔離 * @return */ boolean isIgnore() default true; }
4.注解切面類(lèi)
ps:如果方法或者類(lèi)上有其他注解用到租戶(hù)隔離的,如:日志注解,字典翻譯注解在point.proceed()后執(zhí)行邏輯。需要注意切面類(lèi)的執(zhí)行順序,一定要保證TenantIgnoreAspect 先執(zhí)行,不然其它注解還是會(huì)有租戶(hù)隔離的情況??梢栽赥enantIgnoreAspect 切面類(lèi)加上@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); //判斷類(lèi)上是否有注解 boolean isClassAnnotated = AnnotationUtils.isAnnotationDeclaredLocally(IgnoreTenant.class, targetClass); //判斷方法上是否有注解 boolean isMethodAnnotated = Objects.nonNull(methodIgnoreTenant); //如果類(lèi)上有 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è)查詢(xún),但是只有特定查詢(xún)需要忽略租戶(hù)隔離,可以使用下面的方式
@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忽略多租戶(hù)隔離內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解基于Mybatis-plus多租戶(hù)實(shí)現(xiàn)方案
- SpringBoot集成Mybatis-Plus多租戶(hù)架構(gòu)實(shí)現(xiàn)
- Mybatis-plus多租戶(hù)項(xiàng)目實(shí)戰(zhàn)進(jìn)階指南
- 基于Mybatis-plus實(shí)現(xiàn)多租戶(hù)架構(gòu)的全過(guò)程
- Mybatis-Plus集成Sharding-JDBC與Flyway實(shí)現(xiàn)多租戶(hù)分庫(kù)分表實(shí)戰(zhàn)
- mybatis-plus的多租戶(hù)不同版本實(shí)現(xiàn)的兩種方式
相關(guān)文章
Java使用junit框架進(jìn)行代碼測(cè)試過(guò)程詳解
單元測(cè)試就是針對(duì)最小的功能單元編寫(xiě)測(cè)試代碼,Junit是使用Java語(yǔ)言實(shí)現(xiàn)的單元測(cè)試框架,它是開(kāi)源的,Java開(kāi)發(fā)者都應(yīng)當(dāng)學(xué)習(xí)并使用Junit編寫(xiě)單元測(cè)試。本文就來(lái)講講Junit框架的使用教程,需要的可以參考一下2023-02-02EventBus與Spring Event區(qū)別詳解(EventBus 事件機(jī)制,Spring Event事件機(jī)制)
這篇文章主要介紹了EventBus與Spring Event區(qū)別,需要的朋友可以參考下2020-02-02Java操作集合工具類(lèi)Collections使用詳解
這篇文章主要介紹了java操作集合工具類(lèi)Collections使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12SpringBoot 引?MybatisGenerator的實(shí)現(xiàn)步驟
本文主要介紹了SpringBoot 引?MybatisGenerator的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼
在我們?nèi)粘i_(kāi)發(fā)過(guò)程中,通常會(huì)涉及到數(shù)據(jù)權(quán)限問(wèn)題,本文主要介紹了Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Java 關(guān)鍵字static詳解及實(shí)例代碼
這篇文章主要介紹了Java 關(guān)鍵字static詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel的操作方法
在做一個(gè)?SpringBoot?前后端分離項(xiàng)目的時(shí)候,需要將數(shù)據(jù)存到?Excel中,用戶(hù)可以下載?Excel,具體實(shí)現(xiàn)是采用?Apache?強(qiáng)大的?POI,本文給大家介紹Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel相關(guān)知識(shí),感興趣的朋友一起看看吧2023-09-09