SpringBoot2(十六)mybatis拦截
有不懂的地方,可以查看 pagehelper-spring-boot-starter 源码,PageHelper 就是基于 Interceptor 实现的。
业务需求
拦截 mybatis 的查询结果,对数据进行脱敏处理。
拦截 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; } } }
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!