Spring配置动态数据源实现读写分离的方法
前言
最近因为工作的需要,要搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,有需要的朋友们可以参考学习。
首先是配置数据源
<!--读数据源配置--> <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)中查询方法时会切换到读数据源,增、删、改方法会切换到写数据源。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
相关文章
spring boot加载freemarker模板路径的方法
这篇文章主要介绍了spring boot加载freemarker模板路径的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-11-11解决使用stream将list转map时,key重复导致报错的问题
这篇文章主要介绍了解决使用stream将list转map时,key重复导致报错的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06eclipse/intellij idea 查看java源码和注释方法
下面小编就为大家带来一篇eclipse/intellij idea 查看java源码和注释方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-05-05IDEA 中创建并部署 JavaWeb 程序的方法步骤(图文)
本文主要介绍了IDEA 中创建并部署 JavaWeb 程序的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2022-02-02
最新评论