摘要:本文模擬一下在主庫查詢訂單資訊查詢不到的時候,切換資料源去歷史庫里面查詢,
本文分享自華為云社區《springboot動態切換資料源》,作者:小陳沒煩惱 ,
前言
在公司的系統里,由于資料量較大,所以配置了多個資料源,它會根據用戶所在的地區去查詢那一個資料庫,這樣就產生了動態切換資料源的場景,
今天,就模擬一下在主庫查詢訂單資訊查詢不到的時候,切換資料源去歷史庫里面查詢,
實作效果
首先我們設定查詢的資料庫為db1,可以看到通過訂單號沒有查到訂單資訊,然后我們重置資料源,重新設定為db2,同樣的訂單號就可以查詢到資訊,
資料庫準備
新建兩個資料庫db1和db2,db1作為主庫,db2作為歷史庫
兩個庫中都有一個訂單表biz_order,主庫中沒有資料,歷史庫中有我們要查詢的資料,

代碼撰寫
1.新建一個springboot專案,引入所需依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--引入druid-替換默認資料庫連接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.15</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <!--mysql驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2.application.yaml配置資料庫資訊
這里我們配置兩個資料庫的資訊
spring: datasource: db1: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost/db1?characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource db2: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost/db2?characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource mybatis: mapper-locations: classpath:mapper/*.xml
3.創建資料源物件,并注入spring容器中
新建DynamicDataSourceConfig.java檔案,在該組態檔中讀取yaml配置的資料源資訊,并且通過該資訊構造資料源物件,然后通過@Bean注解注入到spring容器中,
package com.it1997.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; @Configuration public class DynamicDataSourceConfig { @Bean("dataSource1") @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource oneDruidDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean("dataSource2") @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource twoDruidDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public DataSourceTransactionManager dataSourceTransactionManager1(@Qualifier("dataSource1") DataSource dataSource1) { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource1); return dataSourceTransactionManager; } @Bean public DataSourceTransactionManager dataSourceTransactionManager2(@Qualifier("dataSource2") DataSource dataSource2) { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource2); return dataSourceTransactionManager; } }
4.資料源配置背景關系資訊
新建DynamicDataSourceHolder.java檔案,該檔案通過ThreadLocal,實作為每一個執行緒創建一個保存資料源配置的背景關系,并且提供setDataSource和getDataSource靜態方法來設定和獲取資料源的名稱,
package com.it1997.config; public class DynamicDataSourceHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSource(String dataSource) { contextHolder.set(dataSource); } public static String getDataSource() { return contextHolder.get(); } public static void clearDataSource() { contextHolder.remove(); } }
5.重寫資料源配置類
新建DynamicDataSource.java檔案,該類繼承AbstractRoutingDataSource 類,重寫父類determineCurrentLookupKey和afterPropertiesSet方法,
這里我們重寫父類中afterPropertiesSet方法(為什么要重寫在這個方法,可以看文章最后對于druid的原始碼的講解),在這個方法里我們將spring容器中的所有的資料源,都給放到map里,然后后續我們根據map中的key來獲取不同的資料源,super.afterPropertiesSet();通過這個方法設定上資料源,
在類上加上@Primary注解,讓spring容器優先使用我們自定義的資料源,否則還是會使用默認的資料源配置,
package com.it1997.config; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; import org.springframework.stereotype.Component; import javax.annotation.Resource; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; @Component @Primary public class DynamicDataSource extends AbstractRoutingDataSource { @Resource DataSource dataSource1; @Resource DataSource dataSource2; @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSource(); } @Override public void afterPropertiesSet() { // 初始化所有資料源 Map<Object, Object> targetDataSource = new HashMap<>(); targetDataSource.put("db1", dataSource1); targetDataSource.put("db2", dataSource2); super.setTargetDataSources(targetDataSource); super.setDefaultTargetDataSource(dataSource1); super.afterPropertiesSet(); } }
druid資料源配置解讀
點開我們剛剛繼承的AbstractRoutingDataSource抽象類,可以看到它又繼承了AbstractDataSource 實作了InitializingBean介面,
然后我們在看一下druid的資料源配置是怎么實作的,點開DruidDataSourceWrapper類,可以看到它也是繼承了AbstractDataSource 實作了InitializingBean介面,并且,讀取的是yaml檔案中spring.datasource.druid下面配置的資料庫連接資訊,
而我們自定的一的資料源讀取的是spring.datasource.db1下面配置的資料庫連接資訊,
druid的資料源配置,實作了介面中afterPropertiesSet,在這個方法中設定了資料庫的基本資訊,例如,資料庫連接地址、用戶名、密碼以及資料庫連接驅動資訊,
點擊關注,第一時間了解華為云新鮮技術~
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/553484.html
標籤:其他
下一篇:返回列表
