• 阿里P7教你如何使用 Spring 配置动态数据源实现读写分离


    最近搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,以供参考。

    关键词:DataSource 、AbstractRoutingDataSource、AOP

    首先是配置数据源

    <!--读数据源配置-->
    <bean id="readDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"destroy-method="close">
    //配置省略
    </bean>
    <!--写数据源配置-->
    <bean id="writeDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"destroy-method="close">
    //配置省略
    </bean>
    <!-- 动态数据源 -->
    <bean id = "dataSource" class="com.potato.common.bean.DynamicDataSource" >
    <!-- 已配置的数据源 -->
    <property name="targetDataSources">
    <map>
    <entry key="READ" value-ref="readDataSource"/>
    <entry key="WRITE" value-ref="writeDataSource"/>
    </map>
    </property>
    <!-- 默认的数据源 -->
    <property name="defaultTargetDataSource" ref="writeDataSource"/>
    </bean>

    数据源是如何切换的呢?

    通过动态数据源的配置我们知道原来是通过key来进行切换,这里要使用到org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource,我们可以编写自己的动态数据源类DynamicDataSource来继承它。

    public class DynamicDataSource extends AbstractRoutingDataSource { 
    @Override
    protected Object determineCurrentLookupKey() {
    return DataSourceContextHolder.getType();
    }
    }

    还需要一个存放key的地方DataSourceContextHolder 为保证切换时线程安全我们使用ThreadLocal来保存我们的key。

    public class DataSourceContextHolder {
    private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceContextHolder.class);
    public static final String DATA_SOURCE_WRITE = "WRITE";
    public static final String DATA_SOURCE_READ = "READ";
    // 线程本地环境
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    // 设置数据源类型
    public static void setType(String type) {
    if(LOGGER.isDebugEnabled())
    LOGGER.debug("==============切换数据源,类型:"+type+"================");
    contextHolder.set(type);
    }
    // 获取数据源类型
    public static String getType() {
    return (contextHolder.get());
    }
    // 清除数据源类型
    public static void clearType() {
    contextHolder.remove();
    }
    }

    好了,我们可以通过操作DataSourceContextHolder来实现数据源动态的切换了。小伙伴们可能会说了,难道每次调用方法都要手动选择要切换的数据源类型?当然不是啦,Spring AOP登场。

    @Component
    @Aspect
    public class DynamicDataSourceAspect {
    @Pointcut("execution (* com.potato.orm.mapper.*.select*(..)) || execution (* com.potato.orm.mapper.*.count*(..)) ")
    public void readMethodPointcut() {}
    @Pointcut("execution (* com.potato.orm.mapper.*.insert*(..)) || execution (* com.potato.orm.mapper.*.update*(..)) || execution (* com.potato.orm.mapper.*.delete*(..))")
    public void writeMethodPointcut() {}
    @Before("readMethodPointcut()")
    public void switchReadDataSource(){
    //System.out.println("============切换到读数据源===========");
    DataSourceContextHolder.setType(DataSourceContextHolder.DATA_SOURCE_READ);
    }
    @Before("writeMethodPointcut()")
    public void switchWriteDataSource(){
    //System.out.println("=============切换到写数据源==========");
    DataSourceContextHolder.setType(DataSourceContextHolder.DATA_SOURCE_WRITE);
    }
    }

    好啦,在访问Mapper(本项目使用的是MyBatis啦,相当于是DAO)中查询方法时会切换到读数据源,增、删、改方法会切换到写数据源。

    写在最后:欢迎留言讨论,加关注,持续更新!!!

  • 相关阅读:
    git线上操作
    IDEA快捷方式
    Java 四种线程池
    java 获取当前天之后或之前7天日期
    如何理解AWS 网络,如何创建一个多层安全网络架构
    申请 Let's Encrypt 通配符 HTTPS 证书
    GCE 部署 ELK 7.1可视化分析 nginx
    使用 bash 脚本把 AWS EC2 数据备份到 S3
    使用 bash 脚本把 GCE 的数据备份到 GCS
    nginx 配置 https 并强制跳转(lnmp一键安装包)
  • 原文地址:https://www.cnblogs.com/Ti1077/p/9635692.html
Copyright © 2020-2023  润新知