使用简单的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<String> contextHolder=new ThreadLocal<String>();
    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

    }

}

原文地址:https://blog.51cto.com/12133802/2418323

时间: 2024-08-29 18:28:56

使用简单的DataSource类配置主从服务器调用的相关文章

MySQL数据库配置主从服务器实现双机热备

转自:http://www.cnblogs.com/cchun/p/3712637.html 一.安装MySQL 说明:在两台MySQL服务器192.168.21.169和192.168.21.168上分别进行如下操作,安装MySQL 5.5.22  二.配置MySQL主服务器(192.168.21.169) mysql -uroot -p #进入MySQL控制台 create database osyunweidb; #建立数据库osyunweidb insert into mysql.use

Redis配置-主从服务器-phpredis-phpRedisAdmin

1.准备开发环境 yum groupinstall -y "Development Tools" "Server Platform Development" 2.更新时间 3.下载redis-3.2.1.tar.gz,网站地址是:www.redis.io 4.编译安装 tar xf redis-3.2.1.tar.gz cd redis-3.2.1 make 启动redis服务,默认的端口号是6379 注意:有时因为redis配置文件不一样的原因,我们在启动服务配置

mysql5.1.73配置主从服务器

一.安装MySQL 这里就详解,请度娘. 二.配置MySQL主服务器(10.241.226.110) mysql  -uroot  -p    #进入MySQL控制台 create database testdb;   #建立数据库testdb #授权用户mysqlcopy只能从10.241.226.111这个IP访问主服务器10.241.226.110上面的数据库,并且只具有数据库备份的权限 grant replication slave  on *.* to 'mysqlcopy'@'10.

Redis3.2.5配置主从服务器遇到的一些错误

注意:关闭主从服务器的防火墙 问题一: WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 解决一: 这个错误大概是说somaxconn的值128设置过小,从/proc/sys/net/core/somaxconn这个路径也可大概知道这个值的设置是关于网络连接中某个最大值的限定设置,此值表示

配置mysql5.5主从服务器(转)

教程开始:一.安装MySQL 说明:在两台MySQL服务器192.168.21.169和192.168.21.168上分别进行如下操作,安装MySQL 5.5.22  二.配置MySQL主服务器(192.168.21.169)mysql  -uroot  -p    #进入MySQL控制台create database osyunweidb;   #建立数据库osyunweidbinsert into mysql.user(Host,User,Password) values('localhos

Bind简单应用之二(正向解析主从服务器)

DNS主从服务器应用实验 实验环境    系统:Centos 6.3 X64 软件:Bind.x86_64 32:9.8.2-0.10.rc1.el6 主服务器: IP 10.0.0.101:netmask 255.255.255.0 :DNS 10.0.0.102:GW 10.0.0.1 从服务器: IP 10.0.0.102:netmask 255.255.255.0 :DNS 10.0.0.102:GW 10.0.0.1 1.分别在两台服务器上安装Bind软件 #yum install b

利用rsync+inotify实现主从服务器数据同步的简单案例

写在前面:如果此文有幸被某位朋友看见并发现有错的地方,希望批评指正.如有不明白的地方,愿可一起探讨. rsync是Linux下一款非常强大的同步工具,其最大的劣势在于每次执行rsync命令都会遍历目标目录.想象一下这样一种情况:当目录下改动的文件数量并不多且目录下本身文件数量达到一定规模时,每次遍历都会消耗很多资源.那么有没有这样一种工具,当某文件改动后,主动触发rsync命令去同步修改过的文件呢?答案是肯定的,要不然就没有这篇文章了,这个工具就是:inotify. 接下来,本文就利用rsync

MYSQL简单配置主从

*配置Replication**准备两台mysql服务器,版本最好一致,防止版本不同带来的兼容性问题. 第一步:配置 主服务器配置文件:/etc/my.cnf 编辑该文件,添加如下: [mysqld] log-bin=/var/log/mysql/mysql-bin //生成bin文件路径自己指定 server-id=1 //随意设置数字,保证id是唯一的 日志目录:/var/log/mysql 创建: mkdir -p /var/log/mysql chown -R mysql.mysql /

asp.net core 简单部署之FTP配置(CentOS 7.0安装配置Vsftp服务器)

配置过程原文地址:http://www.osyunwei.com/archives/9006.html 坑和结果 正确的跟着这个内容走,是靠谱的. 我自己给自己踩了个坑,请参照文章的朋友注意第七条:七.在/etc/pam.d/vsftpd的文件头部加入以下信息(在后面加入无效) 一些简单操作和命令,小白的我也是吃尽了苦头: cat:查看文件  cat /etc/vsftpd/virtusers vi:编辑文件  vi /etc/vsftpd/virtusers. 编辑文件需要注意,按键盘I是开始