Spring动态数据源实现读写分离详解

网友投稿 311 2023-04-28


Spring动态数据源实现读写分离详解

一、创建基于ThreadLocal的动态数据源容器,保证数据源的线程安全性

package com.bounter.mybayVkGGktis.extension;

/**

* 基于ThreadLocal实现的动态数据源容器,保证DynamicDataSource的线程安全性

* @author simon

*

*/

public class DynamicDataSourceHolder {

private static final ThreadLocal dataSourceHolder = new ThreadLocal<>();

public static void setDataSource(String dataSourceKey) {

dataSourceHolder.set(dataSourceKey);

}

public static String getDataSource() {

return dataSourceHolder.get();

}

public static void clearDataSource() {

dataSourceHolder.remove();

}

}

二、定义Spring动态数据源扩展类,用来实现Master、Slave数据源动态切换

package com.bounter.mybatis.extension;

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

/**

* 自定义的Spring 动态数据源扩展类,用来实现Master、Slave数据源动态切换

* @author simon

*

*/

public class DynamicDataSource extends AbstractRoutingDataSource {

@Override

protected Object determineCurrentLookupKey() {

//使用DynamicDataSourceHolder保证线程安全

return DynamicDataSourceHolder.getDataSource();

}

}

三、配置Master、Slave数据源

1. db.properties配置Master、Slave数据信息

# Master DB

db.master.url=jdbc:mysql://192.168.168.110:3306/bounter?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=PRC&useSSL=false

db.master.username=bounter

# AES encrypt,Base64 encode

db.master.password=ZNhnEjauk3pecZxxS84ofA==

# Slave DB

db.slave.url=jdbc:mysql://192.168.168.111:3306/database?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=PRC&useSSL=false

db.slave.username=bounter

# AES encrypt,Base64 encode

db.slave.password=jFYmt2f57RHhzItYDhWiSA==

2. Spring 配置文件配置Master、Slave连接池,动态数据源

init-method="init" destroy-method="close">

init-method="init" destroy-method="close">

init-method="init" destroy-method="close">

init-method="init" destroy-method="close">

四、创建数据源切面,通过AOP实现根据Dao层方法前缀动态选取读、写数据源

package com.bounter.mybatis.aop;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

import org.springframework.stereotype.Component;

import com.bounter.mybatis.extension.DynamicDataSourceHolder;

/**

* 数据源切面,通过dao方法前缀决定访问读、写数据源

* @author simon

*

*/

@Component

@Aspect

@EnableAspectJAutoProxy(proxyTargetClass = true)

public class DataSourceAspect {

//读库数据源key

private static final String DATASOURCE_KEY_READ = "read";

//查询方法清单

String[] queryMethods = {"find","get","query","count","select"};

/**

* dao层方法执行前选择数据源

* @param point

*/

@Before("execution(* com.bounter.mybatis.dao..*.*(..))")

public void before(JoinPoint point) {

// 获取到当前执行的方法名

String methodName = point.getSignature().getName();

//匹配查询方法

for(String queryMethod : queryMethods) {

if(methodName.startsWith(queryMethod)) {

//查询方法设置数据源为读库

DynamicDataSourceHolder.setDataSource(DATASOURCE_KEY_READ);

break;

}

}

}

/**

* dao层方法执行完后清空数据源选择

* @param point

*/

@After("execution(* com.bounter.mybatis.dao..*.*(..))")

public void after(JoinPoint point) {

DynamicDataSourceHolder.clearDataSource();

}

}

github源码地址:https://github.com/13babybear/bounter-mybatis


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微信小程序 共用变量值的实现
下一篇:Java中Boolean与字符串或者数字1和0的转换实例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~