springboot2 - mybatis拦截
有不懂的地方,可以查看 pagehelper-spring-boot-starter 源码,PageHelper 就是基于 Interceptor 实现的。
业务需求
拦截 mybatis 的查询结果,对数据进行脱敏处理。
这个操作,会从根本上完成脱敏,数据刚查出来就立即脱敏。
报表系统这样做没什么问题,业务系统,一般只是希望客户端脱敏,业务上仍然使用原始数据,这样拦截 Controller 会更合适(本文不讨论这种情况)。
可以拦截的几个接口
- Executor:拦截执行器的方法。
- ParameterHandler:拦截参数的处理。
- ResultHandler:拦截结果集的处理。
- StatementHandler:拦截Sql语法构建的处理。
Interceptor
继承 Interceptor,通过 @Intercepts 注解,说明要拦截的接口、函数。
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.util.Properties;
/**
* 拦截器
*
* @author Mr.css
* @version 2023-06-28 15:53
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
})
public class DesensitizationInterceptor implements Interceptor {
/**
* 数据脱敏工具类
*/
private final ReturnValueDesensitization returnValueDesensitization = new ReturnValueDesensitization();
/**
* 在拦截目标对象的方法时,实际执行的增强逻辑,我们一般在该方法中实现自定义逻辑
*
* @param invocation -
* @return 执行结果
* @throws Throwable -
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object ret = invocation.proceed();
// desensitize data
returnValueDesensitization.process(ret);
return ret;
}
/**
* 生成代理类
*
* @param target 被代理的类,一般是 mybatis 默认的四大拦截
* @return this
*/
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
/**
* 可以用于读取配置文件中通过property标签配置的一些属性,设置一些属性变量
*
* @param properties 环境参数
*/
@Override
public void setProperties(Properties properties) {
// do nothing
}
}
注册拦截器
一种方式,是照抄PageHelper的代码,另一种,可以继承 ConfigurationCustomizer 接口。
在 ConfigurationCustomizer 接口中,可以拿到 Configuration 对象,除了拦截器,还能改动其它很多配置。
import cn.seaboot.admin.mask.ReturnValueDesensitization;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import javax.annotation.Resource;
/**
* mybatis 自定义配置
*
* @author Mr.css
* @version 2023-06-28 14:58
* @see MybatisAutoConfiguration
*/
@EnableConfigurationProperties({PageHelperProperties.class, SeaMybatisProperties.class})
@org.springframework.context.annotation.Configuration
public class MybatisStarter implements ConfigurationCustomizer {
private final Logger logger = LoggerFactory.getLogger(MybatisStarter.class);
@Resource
private PageHelperProperties pageHelperProperties;
@Resource
private SeaMybatisProperties seaMybatisProperties;
@Resource
private ReturnValueDesensitization returnValueDesensitization;
@Override
public void customize(Configuration configuration) {
logger.debug("【Mybatis】using local setting, database-id is: {}", configuration.getDatabaseId());
{
// using page helper
logger.debug("【Mybatis】page-helper:{}", this.pageHelperProperties);
Interceptor interceptor = new PageInterceptor();
interceptor.setProperties(this.pageHelperProperties.getProperties());
if (!containsInterceptor(configuration, interceptor)) {
configuration.addInterceptor(interceptor);
}
}
{
if(seaMybatisProperties.isUsingDesensitize()){
// using desensitize
logger.debug("【Mybatis】using desensitization:{}", DesensitizationInterceptor.class);
Interceptor interceptor = new DesensitizationInterceptor(returnValueDesensitization);
if (!containsInterceptor(configuration, interceptor)) {
configuration.addInterceptor(interceptor);
}
}
}
}
/**
* 是否已经存在相同的拦截器
*
* @param configuration -
* @param interceptor -
* @return -
*/
private boolean containsInterceptor(org.apache.ibatis.session.Configuration configuration, Interceptor interceptor) {
try {
return configuration.getInterceptors().stream().anyMatch(config -> interceptor.getClass().isAssignableFrom(config.getClass()));
} catch (Exception e) {
return false;
}
}
}
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!