mybatisPlus自定义拦截器

mybatisPlus自定义拦截器

一开始数据库的数据是明文存储,后面某些数据需要变成密文保存在数据库,而且密文的字段在很多数据表中都存在。进行select操作时,把密文查询出来并转成明文。
1、使用切面,当接口获取到数据后,遍历数据找到密文字段,把密文解密得到明文
2、使用mybatisPlus自定义拦截器,在sql语句执行前拦截,把 字段 改成 IFNULL(AES_DECRYPT(UNHEX(字段), 密码),字段) AS 字段,sql语句可以解密得到明文。
下面是mybatisPlus自定义拦截器的代码:

@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
    @Resource
    private DataScopeInterceptor dataScopeInterceptor;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 数据权限过滤
        interceptor.addInnerInterceptor(dataScopeInterceptor);
        return interceptor;
    }
}
@Component
public class DataScopeInterceptor implements InnerInterceptor {
	private static Set<SelectItem> selectItemSet = new HashSet<>();
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        String buildSql = boundSql.getSql();
        try {
            Statement statement = CCJSqlParserUtil.parse(buildSql);
            Select select = (Select) statement;
            processSelectBody(select.getSelectBody());
            PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
            mpBoundSql.sql(select.toString());
        } catch (JSQLParserException e) {
            throw ExceptionUtils.mpe("Failed to process, Error SQL: %s", e.getCause(), buildSql);
        } catch (BaseBusinessException be) {
            log.warn(be.getMessage());
        }
    }
    private void processSelectBody(SelectBody selectBody) throws BaseBusinessException, JSQLParserException {
        if (selectBody == null) {
            throw new BaseBusinessException(ResponseCodeEnum.IGNORE_DATA_SCOPE);
            // return;
        }
        if (selectBody instanceof PlainSelect) {
            processPlainSelect((PlainSelect) selectBody);
        } else if (selectBody instanceof WithItem) {
            WithItem withItem = (WithItem) selectBody;
            processSelectBody(withItem.getSelectBody());
        } else {
            SetOperationList operationList = (SetOperationList) selectBody;
            List<SelectBody> selectBodys = operationList.getSelects();
            if (CollectionUtils.isNotEmpty(selectBodys)) {
                for (SelectBody body : selectBodys) {
                    processSelectBody(body);
                }
            }
        }
    }
    private void proprocessPlainSelect(PlainSelect plainSelect) throws JSQLParserException {
        if(selectItemSet.size()>0) selectItemSet = new HashSet<>();
        FromItem fromItem = plainSelect.getFromItem();
        List<Join> joins = plainSelect.getJoins();
        processSelectColumns(plainSelect, fromItem);
        if (CollectionUtils.isNotEmpty(joins)) {
            for (Join join : joins) {
                if (join.isInner() || join.isFull() || join.isSimple()) {
                    FromItem rightItem = join.getRightItem();
                    processSelectColumns(plainSelect, rightItem);
                } else if (join.isLeft()) {
                    FromItem rightItem = join.getRightItem();
                    processSelectColumns(plainSelect, rightItem);
                } else if (join.isRight()) {
                    FromItem rightItem = join.getRightItem();
                    processSelectColumns(plainSelect, rightItem);
                }
            }
        }
        if (selectItemSet.size() == 0) return;
        List<String> filterItem = new ArrayList<>();
        List<SelectItem> selectItemList=selectItemSet.stream()
                .filter(e -> {
                    boolean found = !filterItem.contains(e.toString());
                    filterItem.add(e.toString());
                    return found;
                })
                .collect(Collectors.toList());
        if (selectItemList.size() > 0) {
            plainSelect.setSelectItems(selectItemList);
        }
    }
    // select时解密; *号根据具体的表替换成具体的字段
    private void processSelectColumns(PlainSelect plainSelect, FromItem fromItem) {
    	if (! (fromItem instanceof Table)) return;
        Table table = (Table) fromItem;

        for (SelectItem selectItem : plainSelect.getSelectItems()) {
        	// 1、做判断,不是需要解密的字段和*号就直接add
        	// 2、是需要解密的字段,则变成IFNULL(AES_DECRYPT(UNHEX(字段), 密码),字段) AS 字段,再add
        	// 3、*号则转换成具体的表字段,遍历表字段,是需要解密的字段则转换后add,不是就直接add。add前需要把字段String变成selectItem
        	// 最后。 sql语句会出现 table b;b.id bid、b.id、id;等情况,根据实际情况判断
        	selectItemSet.add(selectItem);
        }
    }
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MybatisPlus是Mybatis的增强版本,它提供了更多的功能和便利的操作。自定义拦截器MybatisPlus中的一个重要特性,可以在SQL执行前后进行一些自定义的操作。 下面是一个示例,展示如何在MybatisPlus中自定义拦截器: 1. 创建一个自定义拦截器类,例如`MyQueryInterceptor`,并实现`Interceptor`接口。 ```java public class MyQueryInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { // 在SQL执行前的操作 // ... // 执行原始的SQL语句 Object result = invocation.proceed(); // 在SQL执行后的操作 // ... return result; } } ``` 2. 在MybatisPlus的配置文件中配置自定义拦截器。 ```java @Configuration public class MybatisPlusConfig { @Bean public MyQueryInterceptor myQueryInterceptor() { return new MyQueryInterceptor(); } @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(MyQueryInterceptor myQueryInterceptor) { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(myQueryInterceptor); return interceptor; } } ``` 3. 使用自定义拦截器。 ```java @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> getUserList(String keyword) { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.like("username", keyword); return userMapper.selectList(queryWrapper); } } ``` 以上示例展示了如何在MybatisPlus中自定义拦截器,并在模糊查询时进行特殊字符的转义处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值