最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離

 更新時(shí)間:2021年07月06日 08:54:30   作者:我與黎明道晚安  
本文將結(jié)合實(shí)例代碼,介紹Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1.創(chuàng)建注解

當(dāng)此注解打在類上,不需要傳參,該類下所有查詢接口開啟數(shù)據(jù)隔離;打在方法上默認(rèn)開啟數(shù)據(jù)隔離,傳參為false則該方法關(guān)閉驗(yàn)證

/**
 * 數(shù)據(jù)權(quán)限驗(yàn)證注解
 * @author xiaohua
 * @date 2021/6/23
 */
@Documented
@Target({METHOD, ANNOTATION_TYPE, TYPE})
@Retention(RUNTIME)
public @interface DataPermission {
    /**
     * 是否要進(jìn)行數(shù)據(jù)權(quán)限隔離
     */
    boolean isPermi() default true;
}

2. 具體實(shí)現(xiàn)

@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DataPermissionInterceptor implements Interceptor {
    private static final Logger logger = LoggerFactory.getLogger(DataPermissionInterceptor.class);

    @Autowired
    private TokenService tokenService;

    //掃描的包路徑(根據(jù)自己的項(xiàng)目路徑來),這里是取的配置里的包路徑
    @Value("${permission.package-path}")
    private String packagePath;

    private final static String DEPT_ID = "dept_id";

    private final static String USER_ID = "create_user";

    private static List<String> classNames;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        try {
            LoginInfo user = tokenService.getLoginInfo();
            if (user == null){
                return invocation.proceed();
            }

            List<Long> deptIds = (List<Long>) Convert.toList(user.getDataScope());
            if (deptIds == null){
                deptIds = new ArrayList<>();
            }
            //反射掃包會比較慢,這里做了個(gè)懶加載
            if (classNames == null) {
                synchronized (LazyInit.class){
                    if (classNames == null){
                        //掃描指定包路徑下所有包含指定注解的類
                        Set<Class<?>> classSet = ClassUtil.scanPackageByAnnotation(packagePath, DataPermission.class);
                        if (classSet == null && classSet.size() == 0){
                            classNames = new ArrayList<>();
                        } else {
                            //取得類全名
                            classNames =  classSet.stream().map(Class::getName).collect(Collectors.toList());
                        }
                    }
                }
            }

            // 拿到mybatis的一些對象
            StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
            MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
            MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

            // mappedStatement.getId()為執(zhí)行的mapper方法的全路徑名,newId為執(zhí)行的mapper方法的類全名
            String newId = mappedStatement.getId().substring(0, mappedStatement.getId().lastIndexOf("."));
            // 如果不是指定的方法,直接結(jié)束攔截
            if (!classNames.contains(newId)) {
                return invocation.proceed();
            }
            String newName = mappedStatement.getId().substring(mappedStatement.getId().lastIndexOf(".") + 1, mappedStatement.getId().length());
            //是否開啟數(shù)據(jù)權(quán)限
            boolean isPermi = true;
            Class<?> clazz = Class.forName(newId);
            //遍歷方法
            for (Method method : clazz.getDeclaredMethods()) {
                //方法是否含有DataPermission注解,如果含有注解則將數(shù)據(jù)結(jié)果過濾
                if (method.isAnnotationPresent(DataPermission.class) && newName.equals(method.getName())) {
                    DataPermission dataPermission =  method.getAnnotation(DataPermission.class);
                    if (dataPermission != null) {
                        //不驗(yàn)證
                        if (!dataPermission.isPermi()) {
                            isPermi = false;
                        } else { //開啟驗(yàn)證
                            isPermi = true;
                        }
                    }
                }
            }

            if (isPermi){
                // 獲取到原始sql語句
                String sql = statementHandler.getBoundSql().getSql();

                // 解析并返回新的SQL語句,只處理查詢sql
                if (mappedStatement.getSqlCommandType().toString().equals("SELECT")) {
    //                    String newSql = getNewSql(sql,deptIds,user.getUserId());
                    sql = getSql(sql,deptIds,user.getUserId());
                }
                // 修改sql
                metaObject.setValue("delegate.boundSql.sql", sql);
            }
            return invocation.proceed();
        } catch (Exception e){
            logger.error("數(shù)據(jù)權(quán)限隔離異常:", e);
            return invocation.proceed();
        }

    }
    
    
    /**
     * 解析SQL語句,并返回新的SQL語句
     * 注意,該方法使用了JSqlParser來操作SQL,該依賴包Mybatis-plus已經(jīng)集成了。如果要單獨(dú)使用,請先自行導(dǎo)入依賴
     *
     * @param sql 原SQL
     * @return 新SQL
     */
    private String getSql(String sql,List<Long> deptIds,Long userId) {

        try {
            String condition = "";
            String permissionSql = "(";
            if (deptIds.size() > 0){
                for (Long deptId : deptIds) {
                    if ("(".equals(permissionSql)){
                        permissionSql = permissionSql + deptId;
                    } else {
                        permissionSql = permissionSql + "," + deptId;
                    }
                }
                permissionSql = permissionSql + ")";
                // 修改原語句
                condition = DEPT_ID +" in " + permissionSql;
            } else {
                condition = USER_ID +" = " + userId;
            }

            if (StringUtils.isBlank(condition)){
                return sql;
            }
            Select select = (Select)CCJSqlParserUtil.parse(sql);
            PlainSelect plainSelect = (PlainSelect)select.getSelectBody();
            //取得原SQL的where條件
            final Expression expression = plainSelect.getWhere();
            //增加新的where條件
            final Expression envCondition = CCJSqlParserUtil.parseCondExpression(condition);
            if (expression == null) {
                plainSelect.setWhere(envCondition);
            } else {
                AndExpression andExpression = new AndExpression(expression, envCondition);
                plainSelect.setWhere(andExpression);
            }
            return plainSelect.toString();
        } catch (JSQLParserException e) {
            logger.error("解析原SQL并構(gòu)建新SQL錯(cuò)誤:" + e);
            return sql;
        }
    }

到此這篇關(guān)于Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離的文章就介紹到這了,更多相關(guān)Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 淺談Java并發(fā)中的內(nèi)存模型

    淺談Java并發(fā)中的內(nèi)存模型

    這篇文章主要介紹了Java并發(fā)中的內(nèi)存模型,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • java中Properties文件加載和使用方法

    java中Properties文件加載和使用方法

    這篇文章主要為大家詳細(xì)介紹了java中Properties文件加載和使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Spring Security架構(gòu)以及源碼詳析

    Spring Security架構(gòu)以及源碼詳析

    這篇文章主要給大家介紹了關(guān)于Spring Security架構(gòu)以及源碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • java打包文件成zip、壓縮文件及file.mkdir和mkdirs的區(qū)別詳解

    java打包文件成zip、壓縮文件及file.mkdir和mkdirs的區(qū)別詳解

    這篇文章主要給大家介紹了關(guān)于java打包文件成zip、壓縮文件及file.mkdir和mkdirs區(qū)別詳解的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • Java讀取Properties配置文件的6種方式匯總

    Java讀取Properties配置文件的6種方式匯總

    這篇文章主要給大家介紹了關(guān)于Java讀取Properties配置文件的6種方式,java中的properties文件是一種配置文件,主要用于表達(dá)配置信息,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析

    Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析

    這篇文章主要介紹了Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java通過導(dǎo)出超大Excel文件解決內(nèi)存溢出問題

    Java通過導(dǎo)出超大Excel文件解決內(nèi)存溢出問題

    導(dǎo)出excel是咱Java開發(fā)的必備技能,下面這篇文章主要給大家介紹了關(guān)于Java通過導(dǎo)出超大Excel文件解決內(nèi)存溢出問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • Java教程package和import訪問控制的步驟詳解

    Java教程package和import訪問控制的步驟詳解

    這篇文章主要為大家介紹了Java教程package和import訪問控制的步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • SpringBoot常用注解詳細(xì)整理

    SpringBoot常用注解詳細(xì)整理

    大家好,本篇文章主要講的是SpringBoot常用注解詳細(xì)整理,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • PageHelper在springboot+mybatis框架中的使用步驟及原理解析

    PageHelper在springboot+mybatis框架中的使用步驟及原理解析

    這篇文章主要介紹了PageHelper在springboot+mybatis框架中的使用步驟及原理解析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03

最新評論

阿合奇县| 江西省| 鲁甸县| 绥棱县| 夏邑县| 曲水县| 尼木县| 高要市| 扶余县| 晋中市| 遵义市| 武城县| 溧水县| 额济纳旗| 晋城| 垣曲县| 乃东县| 永春县| 五原县| 泸定县| 新河县| 洞口县| 禄劝| 台州市| 星座| 平和县| 海口市| 香河县| 泰顺县| 瓮安县| 准格尔旗| 景洪市| 哈尔滨市| 临清市| 揭西县| 和平区| 东辽县| 兰考县| 金溪县| 江安县| 来凤县|