最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

MyBatis-Plus演繹:數(shù)據(jù)權(quán)限控制,優(yōu)雅至極!

2023-10-09 12:47 作者:塵緣如夢_  | 我要投稿

前言

項目使用mybaits-plus,所以在mybaits-plus的基礎(chǔ)上增加數(shù)據(jù)權(quán)限的過濾 mybaits-plus自帶數(shù)據(jù)權(quán)限支持,但由于系統(tǒng)數(shù)據(jù)權(quán)限相對復(fù)雜,通過查看文檔發(fā)現(xiàn)好像并不適用,且原項目版本低,所以最終還是通過自己的方式實現(xiàn) 1 數(shù)據(jù)范圍

我們系統(tǒng)相對復(fù)雜,比如可以按機(jī)構(gòu)/用戶等多種維度過濾,并且可以指定全局和某個特定接口的過濾方式 其實數(shù)據(jù)范圍過濾落地也不過是:數(shù)據(jù)表的某字段限制在一個范圍內(nèi),即sql中添加column in (1,2,3...) 不管怎么說第一步都是要獲取用戶的數(shù)據(jù)范圍,比如某用戶的數(shù)據(jù)范圍為機(jī)構(gòu)id為(1,2,3)下的數(shù)據(jù),那么先要獲取(1,2,3) 首先建立一個類來存儲用戶的數(shù)據(jù)范圍,由于數(shù)據(jù)權(quán)限是多維度的,所以存儲的是一個Map>結(jié)構(gòu) ?public class GerneralScope extends HashMap> { ?} 存儲的數(shù)據(jù)類似如下 ?{ ??"org_id": [1,2,3], // 機(jī)構(gòu)id ??"user_id": [], // 為空代表不過濾用戶id ??"xxx_id": [4,8] // 其它為敵 ?} 使用ThreadLocal進(jìn)行暫存,并在拼接sql時使用,這樣可以避免代碼侵入 ?public class ScopeDataHolder { ?? ???public final static ThreadLocal SCOPE_DATA = new ThreadLocal<>(); ?? ???public static GerneralScope get() { ?????GerneralScope gerneralScope = SCOPE_DATA.get(); ?????SCOPE_DATA.remove(); // 獲取一次就刪除 ?????return gerneralScope; ??} ?? ???public static void set(GerneralScope data) { ?????SCOPE_DATA.set(data); ??} ?} 數(shù)據(jù)結(jié)構(gòu)準(zhǔn)備好了,接下來就是獲取當(dāng)前用戶數(shù)據(jù)范圍存入ScopeDataHolder,采用注解+AOP的方式避免代碼侵入 新增注解@Scope ?@Documented ?@Retention(RetentionPolicy.RUNTIME) ?@Target(ElementType.METHOD) ?public @interface Scope { ???ApiType value() default ApiType.COMMON; ?} 其中加一個參數(shù)value用來區(qū)分不同接口,即可實現(xiàn)特定接口單獨(dú)過濾方式 AOP獲取并設(shè)置數(shù)據(jù)范圍 ?@Component ?public class ScopeAspect { ?? ??@Pointcut("@annotation(com.xxx.Scope)") ???public void injectScope() { ??} ?? ???/** ???* 注入數(shù)據(jù)權(quán)限 ???* @param joinPoint ???* @return ???*/ ???@Before("injectScope()") ???public void around(JoinPoint joinPoint) { ?????Scope annotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(Scope.class); ?????GerneralScope userScopeData = getCurrentUserScopeData(annotation.value()); // 數(shù)據(jù)庫獲取當(dāng)前用戶+當(dāng)前接口的數(shù)據(jù)范圍 ?????ScopeDataHolder.set(userScopeData); // 存入ThreadLocal ??} ?} 到此,零侵入代碼情況下,通過ThreadLocal暫存了用戶所配的數(shù)據(jù)范圍 2 修改SQL

獲取到了用戶的數(shù)據(jù)范圍,下一步就是在查詢中加入數(shù)據(jù)范圍的過濾,即修改sql 剛開始本來打算用mybaits-plus的自定義攔截器實現(xiàn)sql的修改,后來發(fā)現(xiàn)有很多坑,主要是當(dāng)sql中存在left join且分頁時,mybaits-plus的分頁器在count查詢時自動把沒有查詢條件的left join表去掉,如果限定數(shù)據(jù)范圍的字段剛好在join表上,就會導(dǎo)致錯誤 所以最終沒有采用攔截器,而是采取重寫mybaits-plus的QueryWrapper類來實現(xiàn),代碼如下 ?public class ScopeQueryWrapper extends QueryWrapper { ?? ???private final GerneralScope queryScope; ?? ???public ScopeQueryWrapper() { ?????this.queryScope = ScopeDataHolder.get(); // 從ThreadLocal獲取數(shù)據(jù)范圍 ?????if (this.queryScope==null) { ???????throw new IllegalStateException(); ????} ??} ?? ???/** ???* 過濾需要篩選的字段 ???* @param column ???*/ ???@SuppressWarnings("unchecked") ???public void scope(ScopeEnum type, SFunction column) { ?????List els = queryScope.get(type.getValue()); ?????if (els!=null && els.size()!=0) { ???????lambda().in(column, els); ????} ??} ?? ???/** ???* 過濾需要篩選的字段 ???* @param fieldName ???*/ ???@SuppressWarnings("unchecked") ???public void scope(ScopeEnum type, String fieldName) { ?????List els = queryScope.get(type.getValue()); ?????if (els!=null && els.size()!=0) { ???????in(fieldName, els); ????} ??} ?} 這樣只需在查詢層把QueryWrapper替換為ScopeQueryWrapper,并使用scopeFilter方法來指定界限字段即可,寫法如下 ?public Page page(UserQuery query) { ???Page page = new Page<>(query.getPageNum(), query.getPageSize()); ???ScopeQueryWrapper wrapper = new ScopeQueryWrapper<>(); ???if (query.getName()!=null) { ?????wrapper.lambda().like(User::getName,query.getName()); ??} ???/** 數(shù)據(jù)權(quán)限 start **/ ???wrapper.scope(ScopeEnum.orgId, User:getOrgId); // 指定機(jī)構(gòu)id字段 ???wrapper.scope(ScopeEnum.userId, "user.id"); // 指定用戶id字段,字符串方式可以防止join字段重名 ??...省略其它過濾條件 ???/** 數(shù)據(jù)權(quán)限 end**/ ???wrapper.lambda().orderByDesc(User::getId); ???Page result = page(page, wrapper); ???return result; ?} 如上,需要指定具體需要過濾的字段,由于是多維度,可能會指定很多,ScopeEnum即各維度的枚舉,scope方法中的getValue獲取到的即用戶設(shè)置范圍數(shù)據(jù)的key

ScopeEnum scope接受字符串形式,可以避免join時字段有歧義 以上代碼出現(xiàn)了代碼的侵入,但自認(rèn)為可以接受,如果不需要多維度可以進(jìn)一步簡略 最終,執(zhí)行的sql大體如下 ?select * from user where name like "%pq%" and org_id in (1,2,3) and user.id in (4,8,10)

MyBatis-Plus演繹:數(shù)據(jù)權(quán)限控制,優(yōu)雅至極!的評論 (共 條)

分享到微博請遵守國家法律
永吉县| 泸定县| 商丘市| 保靖县| 青海省| 义乌市| 新龙县| 酉阳| 河北省| 茌平县| 科技| 宜昌市| 新余市| 清徐县| 武胜县| 莫力| 临漳县| 建湖县| 东台市| 姚安县| 扎鲁特旗| 泸西县| 东辽县| 新竹县| 平阴县| 湾仔区| 山东省| 广州市| 安国市| 望都县| 班戈县| 隆林| 博湖县| 赤峰市| 马山县| 吉林市| 陵川县| 洞头县| 苍溪县| 夹江县| 高密市|