Spring配置動(dòng)態(tài)數(shù)據(jù)源實(shí)現(xiàn)讀寫分離的方法
前言
最近因?yàn)楣ぷ鞯男枰?,要搭建的一個(gè)項(xiàng)目需要實(shí)現(xiàn)數(shù)據(jù)源的讀寫分離,在這里將代碼進(jìn)行分享,有需要的朋友們可以參考學(xué)習(xí)。
首先是配置數(shù)據(jù)源
<!--讀數(shù)據(jù)源配置--> <bean id="readDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"destroy-method="close"> //配置省略 </bean> <!--寫數(shù)據(jù)源配置--> <bean id="writeDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"destroy-method="close"> //配置省略 </bean> <!-- 動(dòng)態(tài)數(shù)據(jù)源 --> <bean id = "dataSource" class="com.potato.common.bean.DynamicDataSource" > <!-- 已配置的數(shù)據(jù)源 --> <property name="targetDataSources"> <map> <entry key="READ" value-ref="readDataSource"/> <entry key="WRITE" value-ref="writeDataSource"/> </map> </property> <!-- 默認(rèn)的數(shù)據(jù)源 --> <property name="defaultTargetDataSource" ref="writeDataSource"/> </bean>
數(shù)據(jù)源是如何切換的呢?通過(guò)動(dòng)態(tài)數(shù)據(jù)源的配置我們知道原來(lái)是通過(guò)key來(lái)進(jìn)行切換,這里要使用到org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
,我們可以編寫自己的動(dòng)態(tài)數(shù)據(jù)源類DynamicDataSource
來(lái)繼承它。
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getType(); } }
還需要一個(gè)存放key的地方DataSourceContextHolder
為保證切換時(shí)線程安全我們使用ThreadLocal
來(lái)保存我們的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"; // 線程本地環(huán)境 private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); // 設(shè)置數(shù)據(jù)源類型 public static void setType(String type) { if(LOGGER.isDebugEnabled()) LOGGER.debug("==============切換數(shù)據(jù)源,類型:"+type+"================"); contextHolder.set(type); } // 獲取數(shù)據(jù)源類型 public static String getType() { return (contextHolder.get()); } // 清除數(shù)據(jù)源類型 public static void clearType() { contextHolder.remove(); } }
好了,我們可以通過(guò)操作DataSourceContextHolder
來(lái)實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)的切換了。小伙伴們可能會(huì)說(shuō)了,難道每次調(diào)用方法都要手動(dòng)選擇要切換的數(shù)據(jù)源類型?當(dāng)然不是啦,Spring AOP登場(chǎng)。
@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("============切換到讀數(shù)據(jù)源==========="); DataSourceContextHolder.setType(DataSourceContextHolder.DATA_SOURCE_READ); } @Before("writeMethodPointcut()") public void switchWriteDataSource(){ //System.out.println("=============切換到寫數(shù)據(jù)源=========="); DataSourceContextHolder.setType(DataSourceContextHolder.DATA_SOURCE_WRITE); } }
總結(jié)
好啦,以上就是這篇文章的全部?jī)?nèi)容了,在訪問(wèn)Mapper(本項(xiàng)目使用的是MyBatis啦,相當(dāng)于是DAO)中查詢方法時(shí)會(huì)切換到讀數(shù)據(jù)源,增、刪、改方法會(huì)切換到寫數(shù)據(jù)源。希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
相關(guān)文章
java 對(duì)稱加密算法實(shí)現(xiàn)詳解
這篇文章主要介紹了java 對(duì)稱加密算法實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07spring boot加載freemarker模板路徑的方法
這篇文章主要介紹了spring boot加載freemarker模板路徑的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問(wèn)題
這篇文章主要介紹了解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06log4j控制臺(tái)不打印日志故障的詳細(xì)解決方案
這篇文章主要給大家介紹了關(guān)于log4j控制臺(tái)不打印日志故障的詳細(xì)解決方案,log4j不提供默認(rèn)配置,因?yàn)樵谀承┉h(huán)境中可能禁止輸出到控制臺(tái)或文件系統(tǒng),需要的朋友可以參考下2023-08-08java equals和=,==的區(qū)別詳細(xì)介紹
這篇文章主要介紹了java equals和=,==的區(qū)別,學(xué)習(xí)Java的朋友對(duì)equals 和== 這個(gè)概念開(kāi)始使用的時(shí)候會(huì)有疑問(wèn),很難辨別如何正確使用,這里幫大家詳細(xì)講解該知識(shí)點(diǎn),希望大家能掌握,有需要的小伙伴可以參考下2016-10-10eclipse/intellij idea 查看java源碼和注釋方法
下面小編就為大家?guī)?lái)一篇eclipse/intellij idea 查看java源碼和注釋方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05IDEA 中創(chuàng)建并部署 JavaWeb 程序的方法步驟(圖文)
本文主要介紹了IDEA 中創(chuàng)建并部署 JavaWeb 程序的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02使用Java對(duì)Hbase操作總結(jié)及示例代碼
這篇文章主要介紹了使用Java對(duì)Hbase進(jìn)行操作總結(jié),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07SpringBoot整合Redis實(shí)現(xiàn)刷票過(guò)濾功能
隨著互聯(lián)網(wǎng)的不斷發(fā)展,網(wǎng)站或APP的用戶流量增加,也衍生出了一些惡意刷量等問(wèn)題,給數(shù)據(jù)分析及運(yùn)營(yíng)帶來(lái)極大的困難,所以本文使用SpringBoot和Redis實(shí)現(xiàn)一個(gè)刷票過(guò)濾功能,需要的可以參考一下2023-06-06