package com.wangzhixuan.commons.intercept;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.util.Properties;
【系统数据隔离|根据mybatis 拦截器实现项目业务数据隔离】import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.wangzhixuan.commons.sqlparser.SelectVisitorImpl;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.select.Select;
@Intercepts({
@Signature(method = “prepare”, type = StatementHandler.class, args = { Connection.class, Integer.class})
})
public class TestInterceptor implements Interceptor {
// 控制器本来就是单例,这样似乎更加合理
protected Logger logger = LogManager.getLogger(getClass());
private CCJSqlParserManager parserManager = new CCJSqlParserManager();
@Override
public Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException {
if(invocation.getTarget() instanceof StatementHandler) {
//逻辑代码区
StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
// 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环
// 可以分离出最原始的的目标类)
while (metaStatementHandler.hasGetter("h")) {
Object object = metaStatementHandler.getValue("h");
metaStatementHandler = SystemMetaObject.forObject(object);
}
// 分离最后一个代理对象的目标类
while (metaStatementHandler.hasGetter("target")) {
Object object = metaStatementHandler.getValue("target");
metaStatementHandler = SystemMetaObject.forObject(object);
}
MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
//获取sql
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
if(sql.contains("NEXTVAL")){ // 去掉子序列函数
return invocation.proceed();
}
//获取方法id
String id = mappedStatement.getId();
if (id.contains("InventoryInoutMapper") || id.contains("selectSaleReportByGmtCreate")
|| id.contains("selectBiShipReportByGmtCreate") || id.contains("selectTransNoinventoryReport")
|| id.contains("queryPurStoDetails") || id.contains("queryTaskDailyCloseIds")) { // 剔除不需要走拦截器的方法
return invocation.proceed();
}
//获得方法类型
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
if ("SELECT".equals(sqlCommandType.toString())) {
//如果是select就将sql转成SELECT对象
try {
Select select = (Select)parserManager.parse(new StringReader(sql));
//访问各个visitor
select.getSelectBody().accept(new SelectVisitorImpl());
//将增强后的sql放回
metaStatementHandler.setValue("delegate.boundSql.sql", select.toString());
return invocation.proceed();
} catch(Throwable e) {
logger.error("拦截器异常Start");
logger.error(e);
logger.error("拦截器异常End");
}
}
}
return invocation.proceed();
}@Override
public Object plugin(Object target) {
//生成代理对象
return Plugin.wrap(target, this);
}@Override
public void setProperties(Properties properties) {
}
}
推荐阅读
- 框架|Mybatis的一级缓存和二级缓存
- Mybatis日志工厂
- MyBatis的功能架构是怎样的
- Mybatis入门之CRUD
- mybatis之缓存机制
- Mybatis练习(1)
- Java|MyBatis(五)——MyBatis中的缓存机制
- mybatis之脚本解析器
- mybatis|记mybatis查询null字段导致的NPE
- Mybatis 动态查询、插入、修改操作