使用简单的DataSource类配置主从服务器调用

配置三个类

大家创建这三个类,配合> https://blog.51cto.com/12133802/2418053 使用即可

为惠城等地区用户提供了全套网页设计制作服务,及惠城网站建设行业解决方案。主营业务为网站建设、成都网站设计、惠城网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

DynamicDataSource类


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{

    @Override
    protected Object determineCurrentLookupKey() {
        // TODO Auto-generated method stub
        return DynamicDataSourceHolder.getDBType();
    }

}

DynamicDataSourceHolder类


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DynamicDataSourceHolder {

    private static Logger logger=LoggerFactory.getLogger(DynamicDataSourceHolder.class);
    private static ThreadLocal contextHolder=new ThreadLocal();
    public static final String DB_MASTER = "master";
    public static final String DB_SLAVE="slave";

    public static String getDBType() {
        String db=contextHolder.get();
        if(db==null) {
            db=DB_MASTER;
        }
        return db;

    }

    /**
     * 设置线程的DBType
     * @param str
     */
    public static void setDBType(String str) {
        logger.debug("所使用的数据源为:"+str);
        contextHolder.set(str);
    }
    /**
     * 清理线程
     */
    public static void clearDBType() {
        contextHolder.remove();
    }

DynamicDataSourceInterceptor拦截器类


import java.util.Locale;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
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.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager;

//增删改的操作都在update里面,RowBounds.class,ResultHandler.class是处理返回结果的
@Intercepts({
    @Signature(type=Executor.class,method="update",args= {MappedStatement.class,Object.class}),
    @Signature(type=Executor.class,method="query",args= {MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})
})
public class DynamicDataSourceInterceptor implements Interceptor{

    private static Logger logger=LoggerFactory.getLogger(DynamicDataSourceInterceptor.class);

    //正则表达式,判断是否是增删改
    private static final String REGEX=".*insert\\u0020.*|.*delete\\u0020.*|.*update\\u0020.*";

    //什么情况去做拦截
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //查看调用的方法是否使用了事物
        boolean synchronizationActive=TransactionSynchronizationManager.isActualTransactionActive();
        //获取到方法的参数
        Object[] objects=invocation.getArgs();

        //增删改查操作一般在头部第一个会记录,也就是object[0]中可以获取的到
        MappedStatement ms=(MappedStatement)objects[0];

        String lookupKey=DynamicDataSourceHolder.DB_MASTER;
        //读方法
        if(synchronizationActive!=true) {

            if(ms.getSqlCommandType().equals(SqlCommandType.SELECT)) {
                //selectKey为自增ID查询主键(SELECT LAST_INSERT_ID())方法,使用主库
                //就是添加例如商品信息,自增ID并返回这个ID的情况
                if(ms.getId().contains(SelectKeyGenerator.SELECT_KEY_SUFFIX)) {
                    lookupKey=DynamicDataSourceHolder.DB_MASTER;
                }else {
                    BoundSql boundSql=ms.getSqlSource().getBoundSql(objects[1]);
                    String sql=boundSql.getSql().toLowerCase(Locale.CHINA).replaceAll("[\\t\\n\\r]"," ");
                    //使用正则判断
                    if(sql.matches(REGEX)) {
                        //主库
                        lookupKey=DynamicDataSourceHolder.DB_MASTER;
                    }else {
                        //从库
                        lookupKey=DynamicDataSourceHolder.DB_SLAVE;
                    }
                }
            }
        }else {
            lookupKey=DynamicDataSourceHolder.DB_MASTER;
        }

        logger.debug("设置方法 [{}] use [{}] Strategy,SqlCommanType [{}]",ms.getId(),lookupKey,
                ms.getSqlCommandType().name());

        DynamicDataSourceHolder.setDBType(lookupKey);
        return invocation.proceed();
    }

    //是否使用代理包装
    @Override
    public Object plugin(Object target) {

        if(target instanceof Executor) {
            return Plugin.wrap(target, this);
        }else {
            return target;
        }
    }

    //初始化时做相关设置
    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub

    }

}

本文标题:使用简单的DataSource类配置主从服务器调用
文章位置:http://scyanting.com/article/ggcooc.html