- 拦截器
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DataAuthInterceptor implements Interceptor {
//关键字
private String dataAuthScope = "xxx";
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql;
// 通过MetaObject访问对象的属性
MetaObject metaObject = MetaObject.forObject(
statementHandler,
SystemMetaObject.DEFAULT_OBJECT_FACTORY,
SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
new DefaultReflectorFactory());
// 获取成员变量mappedStatement
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
//验证是否需要拦截
if (!needToBeIntercepted(mappedStatement.getId())) {
return invocation.proceed();
}
boundSql = statementHandler.getBoundSql();
//获取到原始sql语句
String sql = boundSql.getSql();
//多个空格替换为一个空格
sql = sql.replaceAll("\\s{1,}", " ");
//如果查询关键字可以进行数据权限过滤
if (sql.indexOf(dataAuthScope) >= 0) {
//权限sql
String dataAuthSql = "xxx";
//关键字替换
String replace = sql.replace(dataAuthScope, dataAuthSql.toString());
log.debug("=====DataAuth sql rewrite: sql:={}", replace);
//通过反射修改sql语句
Field field = boundSql.getClass().getDeclaredField("sql");
field.setAccessible(true);
field.set(boundSql, replace);
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
/**
* 判断是否需要被拦截
*/
private boolean needToBeIntercepted(String methodFullPath) throws ClassNotFoundException {
String classFullPath = methodFullPath.substring(0, methodFullPath.lastIndexOf("."));
String methodSimpleName = methodFullPath.substring(methodFullPath.lastIndexOf(".") + 1);
if (methodSimpleName.endsWith("_COUNT")){//分页处理
methodSimpleName = methodSimpleName.replace("_COUNT", "");
}
for (Method method : Class.forName(classFullPath).getDeclaredMethods()) {
if (method.getName().equals(methodSimpleName)) {
if ( method.getAnnotation(MapperDataScope.class) != null) {
return true;
}
}
}
return false;
}
- 新建配置类
/**
* mybatis自定义拦截器
*/
@Configuration
public class MybatisInterceptorAutoConfiguration {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
/**
* 只会执行一次
* 顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
*/
@PostConstruct
public void addMysqlInterceptor() {
//创建自定义mybatis拦截器,添加到chain的最后面
DataAuthInterceptor interceptor = new DataAuthInterceptor();
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
//自己添加
configuration.addInterceptor(interceptor);
}
}
}