根据mybatis 拦截器实现项目业务数据隔离

package com.wangzhixuan.commons.intercept;

import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.util.Properties;

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,拦截器,业务数据隔离)