MybatisPlus实现数据拦截的使用示例

 更新时间:2023年10月13日 15:34:18   作者:Younger成  
在MyBatis-Plus中,可以通过自定义拦截器来实现对SQL语句的拦截和修改,本文就来介绍一下如何使用,具有一定的参考价值,感兴趣的可以了解一下

基于配置文件实现(关键key存储在配置文件,通过读取配置文件来实现动态拼接sql)

1、创建注解类

@UserDataPermission(id="app")

注:id用以区分是小程序还是应用程序

注解加的位置:

2、配置枚举类配置文件 EDataPermissionType

3、创建拦截器重写InnerInterceptor接口,重写查询方法

/**
 * 拦截器
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class MyDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
    /**
     * 数据权限处理器
     */
    private MyDataPermissionHandler dataPermissionHandler;
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
            return;
        }
        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
        mpBs.sql(this.parserSingle(mpBs.sql(), ms.getId()));
    }
    @Override
    protected void processSelect(Select select, int index, String sql, Object obj) {
        SelectBody selectBody = select.getSelectBody();
        if (selectBody instanceof PlainSelect) {
            this.setWhere((PlainSelect) selectBody, (String) obj);
        } else if (selectBody instanceof SetOperationList) {
            SetOperationList setOperationList = (SetOperationList) selectBody;
            List<SelectBody> selectBodyList = setOperationList.getSelects();
            selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
        }
    }
 /**
     * 设置 where 条件
     *
     * @param plainSelect  查询对象
     * @param whereSegment 查询条件片段
     */
    private void setWhere(PlainSelect plainSelect, String whereSegment) {
        Expression sqlSegment = this.dataPermissionHandler.getSqlSegment(plainSelect, whereSegment);
        if (null != sqlSegment) {
            plainSelect.setWhere(sqlSegment);
        }
    }
}

4、创建处理类,动态拼接sql片段,设置where

/**
 * 拦截器处理器
 */
@Slf4j
public class MyDataPermissionHandler {
    private ISysUserDataRelationService sysUserDataRelationService = new SysUserDataRelationServiceImpl();
    private MpcTokenUtil mpcTokenUtil = new MpcTokenUtil();
    private AppManageConfig appManageConfig;
    /**
     * 获取数据权限 SQL 片段
     *
     * @param plainSelect  查询对象
     * @param whereSegment 查询条件片段
     * @return JSqlParser 条件表达式
     */
    @SneakyThrows(Exception.class)
    public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
        sysUserDataRelationService = SpringUtils.getBean(ISysUserDataRelationService.class);
        mpcTokenUtil = SpringUtils.getBean(MpcTokenUtil.class);
        appManageConfig = SpringUtils.getBean(AppManageConfig.class);
        // 待执行 SQL Where 条件表达式
        Expression where = plainSelect.getWhere();
        if (where == null) {
            where = new HexValue(" 1 = 1 ");
        }
        //获取mapper名称
        String className = whereSegment.substring(0, whereSegment.lastIndexOf("."));
        //获取方法名
        String methodName = whereSegment.substring(whereSegment.lastIndexOf(".") + 1);
        Table fromItem = (Table) plainSelect.getFromItem();
        // 有别名用别名,无别名用表名,防止字段冲突报错
        Alias fromItemAlias = fromItem.getAlias();
        String mainTableName = fromItemAlias == null ? fromItem.getName() : fromItemAlias.getName();
        //获取当前mapper 的方法
        Method[] methods = Class.forName(className).getMethods();
        //遍历判断mapper 的所有方法,判断方法上是否有 UserDataPermission
        for (Method m : methods) {
            if (Objects.equals(m.getName(), methodName)) {
                UserDataPermission annotation = m.getAnnotation(UserDataPermission.class);
                if (annotation == null) {
                    return where;
                }
                String type = annotation.id();
                //小程序或应用程序的集合,in的范围
                List<String> dataIds = sysUserDataRelationService.getUserPermission(mpcTokenUtil.getUserAccountByToken(), EDataPermissionType.getCode(type));
                if (CollectionUtils.isEmpty(dataIds)) {
                    return null;
                }
                log.info("开始进行权限过滤,where: {},mappedStatementId: {}", where, whereSegment);
                // 把集合转变为JSQLParser需要的元素列表
                ItemsList ids = new ExpressionList(dataIds.stream().map(StringValue::new).collect(Collectors.toList()));
                //in表达式的写法
                InExpression inExpressiondept = null;
                String key = appManageConfig.getList().get(type);
                inExpressiondept = new InExpression(new Column(mainTableName + "." + key), ids);
                return new AndExpression(where, inExpressiondept);
            }
        }
        //说明无权查看,
        where = new HexValue(" 1 = 2 ");
        return where;
    }
}

5、将拦截器加到mybatis-plus插件中

@Configuration
@MapperScan("com.shinho.mpc.mapper")
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
    /**
     * 将拦截器加到mybatis插件中
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加数据权限插件
        MyDataPermissionInterceptor dataPermissionInterceptor = new MyDataPermissionInterceptor();
        // 添加自定义的数据权限处理器
        dataPermissionInterceptor.setDataPermissionHandler(new MyDataPermissionHandler());
        interceptor.addInnerInterceptor(dataPermissionInterceptor);
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

6、使用的位置加注解即可生效

在mapper层加上注解:

@UserDataPermission(id="app")
  • id :注解入参
  • app:应用程序类型权限控制
  • mp:小程序类型权限控制

7、数据拦截效果:

到此这篇关于MybatisPlus实现数据拦截的使用示例的文章就介绍到这了,更多相关MybatisPlus 数据拦截 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java集合框架 arrayblockingqueue应用分析

    java集合框架 arrayblockingqueue应用分析

    ArrayBlockingQueue是一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素
    2012-11-11
  • Spring事务中的事务传播行为使用方式详解

    Spring事务中的事务传播行为使用方式详解

    Spring框架作为一个轻量级的开源框架,在企业应用开发中被广泛使用,在Spring事务管理中,事务传播行为是非常重要的一部分,它定义了方法如何参与到已经存在的事务中或者如何开启新的事务,本文将详细介绍Spring事务中的几种事务传播行为,详细讲解具体使用方法
    2023-06-06
  • MybatisPlus实现分页效果并解决错误问题:cant found IPage for args

    MybatisPlus实现分页效果并解决错误问题:cant found IPage for args

    这篇文章主要介绍了MybatisPlus实现分页效果并解决错误:cant found IPage for args,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • 快速学会Dubbo的配置环境及相关配置

    快速学会Dubbo的配置环境及相关配置

    本文主要讲解Dubbo的环境与配置,文中运用大量代码和图片讲解的非常详细,需要学习或用到相关知识的小伙伴可以参考这篇文章
    2021-09-09
  • Java拷贝数组方法Arrays.copyOf()是地址传递的证明实例

    Java拷贝数组方法Arrays.copyOf()是地址传递的证明实例

    今天小编就为大家分享一篇关于Java拷贝数组方法Arrays.copyOf()是地址传递的证明实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • eclipse 联想功能设置技巧

    eclipse 联想功能设置技巧

    本文主要介绍了eclipse 联想功能设置技巧的相关内容,还是比较不错的,需要的朋友可以参考。
    2017-10-10
  • Java使用JDK与Cglib动态代理技术统一管理日志记录

    Java使用JDK与Cglib动态代理技术统一管理日志记录

    这篇文章主要介绍了Java使用JDK与Cglib动态代理技术统一管理日志记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Java如何获取对象属性及对应值

    Java如何获取对象属性及对应值

    这篇文章主要介绍了Java如何获取对象属性及对应值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • 解决myBatis中openSession()自动提交的问题

    解决myBatis中openSession()自动提交的问题

    在学习MySQL过程中,发现插入操作自动提交,问题原因可能是myBatis中的openSession()方法设置了自动提交,或者是MySQL的默认引擎设置为不支持事务的MyISAM,解决办法包括更改myBatis的提交设置或将MySQL表的引擎改为InnoDB
    2024-09-09
  • java小知识之查询数据库数据的元信息

    java小知识之查询数据库数据的元信息

    这篇文章主要给大家介绍了关于java小知识之查询数据库数据的元信息,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-10-10

最新评论