SpringBoot配置動態(tài)數(shù)據(jù)源
一、動態(tài)多數(shù)據(jù)源的配置
1.1 創(chuàng)建動態(tài)數(shù)據(jù)源
通過實現(xiàn)Spring提供的AbstractRoutingDataSource類,可以實現(xiàn)自己的數(shù)據(jù)源選擇邏輯,從而可以實現(xiàn)數(shù)據(jù)源的動態(tài)切換。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Value("${spring.datasource.default-db-key}")
private String defaultDbKey;·
@Override
protected Object determineCurrentLookupKey() {
String currentDb = DynamicDataSourceService.currentDb();
if (currentDb == null) {
return defaultDbKey;
}
return currentDb;
}
}
1.2 創(chuàng)建動態(tài)數(shù)據(jù)源配置類
跟配置靜態(tài)多數(shù)據(jù)源一樣,需要手動配置下面的三個 Bean,只不過DynamicDataSource類的targetDataSources是空的。
@Configuration
public class DynamicDataSourceConfig {
/**
* 動態(tài)數(shù)據(jù)源
*/
@Bean
public DynamicDataSource dynamicDataSource() {
DynamicDataSource dataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
dataSource.setTargetDataSources(targetDataSources);
return dataSource;
}
/**
* 會話工廠
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
sqlSessionFactoryBean.setConfiguration(configuration);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/repository/*.xml"));
return sqlSessionFactoryBean;
}
/**
* 事務(wù)管理器
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
}
}
1.3 創(chuàng)建動態(tài)數(shù)據(jù)源服務(wù)類
這是一個比較核心的工具類,提供了一些靜態(tài)方法從而可以實現(xiàn)一些功能,包括:動態(tài)添加數(shù)據(jù)源
、切換數(shù)據(jù)源
、重置數(shù)據(jù)源
、獲取數(shù)據(jù)源
。
在 DynamicDataSource 類中,就是調(diào)用了 DynamicDataSourceService 類的 switchDb
方法實現(xiàn)的數(shù)據(jù)源選擇。
通過查看下面的代碼就能看出來使用線程本地的技術(shù)實現(xiàn)的多個請求數(shù)據(jù)源互不相干。
@Slf4j
public class DynamicDataSourceService {
private static final Map<Object, Object> dataSources = new HashMap<>();
private static final ThreadLocal<String> dbKeys = ThreadLocal.withInitial(() -> null);
/**
* 動態(tài)添加一個數(shù)據(jù)源
*
* @param name 數(shù)據(jù)源的key
* @param dataSource 數(shù)據(jù)源對象
*/
public static void addDataSource(String name, DataSource dataSource) {
DynamicDataSource dynamicDataSource = App.context.getBean(DynamicDataSource.class);
dataSources.put(name, dataSource);
dynamicDataSource.setTargetDataSources(dataSources);
dynamicDataSource.afterPropertiesSet();
log.info("addDataSource 添加了數(shù)據(jù)源:{}", name);
}
/**
* 切換數(shù)據(jù)源
*/
public static void switchDb(String dbKey) {
dbKeys.set(dbKey);
log.info("switchDb 切換數(shù)據(jù)源:{}", dbKey);
}
/**
* 重置數(shù)據(jù)源
*/
public static void resetDb() {
dbKeys.remove();
log.info("resetDb 重置數(shù)據(jù)源");
}
/**
* 獲取當前數(shù)據(jù)源
*/
public static String currentDb() {
log.info("currentDb 獲取當前數(shù)據(jù)源");
return dbKeys.get();
}
}
至此,動態(tài)多數(shù)據(jù)源的配置就完成了,只需要編寫數(shù)據(jù)源生成的邏輯,在程序運行時調(diào)用 addDataSource 方法即可將數(shù)據(jù)源動態(tài)添加到上下文中,并支持動態(tài)切換。
下面簡單介紹一下基于配置文件的數(shù)據(jù)源生成。
二、數(shù)據(jù)源生成器
2.1 自定義了一個數(shù)據(jù)源生成器接口用于定義動態(tài)生成數(shù)據(jù)源的要求。
public interface DataSourceProvider {
List<DataSource> provide();
}
2.2 然后編寫了一個根據(jù)配置文件提供數(shù)據(jù)源并配置的實現(xiàn)類。
@Component
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public class YmlDataSourceProvider implements DataSourceProvider {
private List<Map<String, DataSourceProperties>> dataSources;
private DataSource buildDataSource(DataSourceProperties prop) {
DataSourceBuilder<?> builder = DataSourceBuilder.create();
builder.driverClassName(prop.getDriverClassName());
builder.username(prop.getUsername());
builder.password(prop.getPassword());
builder.url(prop.getJdbcUrl());
return builder.build();
}
@Override
public List<DataSource> provide() {
List<DataSource> res = new ArrayList<>();
dataSources.forEach(map -> {
Set<String> keys = map.keySet();
keys.forEach(key -> {
DataSourceProperties properties = map.get(key);
DataSource dataSource = buildDataSource(properties);
DynamicDataSourceService.addDataSource(key, dataSource);
});
});
return res;
}
@PostConstruct
public void init() {
provide();
}
public List<Map<String, DataSourceProperties>> getDataSources() {
return dataSources;
}
public void setDataSources(List<Map<String, DataSourceProperties>> dataSources) {
this.dataSources = dataSources;
}
}
看一下對應的配置文件內(nèi)容:文章來源:http://www.zghlxwxcb.cn/news/detail-702902.html
spring:
datasource:
default-db-key: db0
hikari:
data-sources:
- db0:
jdbc-url: jdbc:mysql://127.0.0.1:3306/codingcea
username: codingce
password: 1234567890
driver-class-name: com.mysql.cj.jdbc.Driver
- db1:
jdbc-url: jdbc:mysql://127.0.0.1:3306/codingceb
username: codingce
password: 1234567890
driver-class-name: com.mysql.cj.jdbc.Driver
這樣就實現(xiàn)了應用啟動時自動將配置文件中的數(shù)據(jù)源配置讀取并生成數(shù)據(jù)源注冊到上下文中;
當然也可以有其他的實現(xiàn),比如從數(shù)據(jù)庫讀取并配置,或者通過接口請求的方式生成都可以,只要實現(xiàn)自己的DataSourceProvider
就可以。文章來源地址http://www.zghlxwxcb.cn/news/detail-702902.html
到了這里,關(guān)于【Java】Spring Boot配置動態(tài)數(shù)據(jù)源的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!