SpringBoot配置动态数据源
一、动态多数据源的配置
1.1 创建动态数据源
通过实现Spring提供的AbstractRoutingDataSource类,可以实现自己的数据源选择逻辑,从而可以实现数据源的动态切换。
publicclassDynamicDataSourceextendsAbstractRoutingDataSource{@Value("${spring.datasource.default-db-key}")privateString defaultDbKey;·
@OverrideprotectedObjectdetermineCurrentLookupKey(){String currentDb =DynamicDataSourceService.currentDb();if(currentDb ==null){return defaultDbKey;}return currentDb;}}
1.2 创建动态数据源配置类
跟配置静态多数据源一样,需要手动配置下面的三个 Bean,只不过DynamicDataSource类的targetDataSources是空的。
@ConfigurationpublicclassDynamicDataSourceConfig{/**
* 动态数据源
*/@BeanpublicDynamicDataSourcedynamicDataSource(){DynamicDataSource dataSource =newDynamicDataSource();Map<Object,Object> targetDataSources =newHashMap<>();
dataSource.setTargetDataSources(targetDataSources);return dataSource;}/**
* 会话工厂
*/@BeanpublicSqlSessionFactoryBeansqlSessionFactoryBean()throwsIOException{org.apache.ibatis.session.Configuration configuration =neworg.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);SqlSessionFactoryBean sqlSessionFactoryBean =newSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
sqlSessionFactoryBean.setConfiguration(configuration);PathMatchingResourcePatternResolver resolver =newPathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/repository/*.xml"));return sqlSessionFactoryBean;}/**
* 事务管理器
*/@BeanpublicPlatformTransactionManagertransactionManager(){returnnewDataSourceTransactionManager(dynamicDataSource());}}
1.3 创建动态数据源服务类
这是一个比较核心的工具类,提供了一些静态方法从而可以实现一些功能,包括:
动态添加数据源
、
切换数据源
、
重置数据源
、
获取数据源
。
在 DynamicDataSource 类中,就是调用了 DynamicDataSourceService 类的 switchDb
方法实现的数据源选择。
通过查看下面的代码就能看出来使用线程本地的技术实现的多个请求数据源互不相干。
@Slf4jpublicclassDynamicDataSourceService{privatestaticfinalMap<Object,Object> dataSources =newHashMap<>();privatestaticfinalThreadLocal<String> dbKeys =ThreadLocal.withInitial(()->null);/**
* 动态添加一个数据源
*
* @param name 数据源的key
* @param dataSource 数据源对象
*/publicstaticvoidaddDataSource(String name,DataSource dataSource){DynamicDataSource dynamicDataSource =App.context.getBean(DynamicDataSource.class);
dataSources.put(name, dataSource);
dynamicDataSource.setTargetDataSources(dataSources);
dynamicDataSource.afterPropertiesSet();
log.info("addDataSource 添加了数据源:{}", name);}/**
* 切换数据源
*/publicstaticvoidswitchDb(String dbKey){
dbKeys.set(dbKey);
log.info("switchDb 切换数据源:{}", dbKey);}/**
* 重置数据源
*/publicstaticvoidresetDb(){
dbKeys.remove();
log.info("resetDb 重置数据源");}/**
* 获取当前数据源
*/publicstaticStringcurrentDb(){
log.info("currentDb 获取当前数据源");return dbKeys.get();}}
至此,动态多数据源的配置就完成了,只需要编写数据源生成的逻辑,在程序运行时调用 addDataSource 方法即可将数据源动态添加到上下文中,并支持动态切换。
下面简单介绍一下基于配置文件的数据源生成。
二、数据源生成器
2.1 自定义了一个数据源生成器接口用于定义动态生成数据源的要求。
publicinterfaceDataSourceProvider{List<DataSource>provide();}
2.2 然后编写了一个根据配置文件提供数据源并配置的实现类。
@Component@ConfigurationProperties(prefix ="spring.datasource.hikari")publicclassYmlDataSourceProviderimplementsDataSourceProvider{privateList<Map<String,DataSourceProperties>> dataSources;privateDataSourcebuildDataSource(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();}@OverridepublicList<DataSource>provide(){List<DataSource> res =newArrayList<>();
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;}@PostConstructpublicvoidinit(){provide();}publicList<Map<String,DataSourceProperties>>getDataSources(){return dataSources;}publicvoidsetDataSources(List<Map<String,DataSourceProperties>> dataSources){this.dataSources = dataSources;}}
看一下对应的配置文件内容:
spring:datasource:default-db-key: db0
hikari:data-sources:-db0:jdbc-url: jdbc:mysql://127.0.0.1:3306/codingcea
username: codingce
password:1234567890driver-class-name: com.mysql.cj.jdbc.Driver
-db1:jdbc-url: jdbc:mysql://127.0.0.1:3306/codingceb
username: codingce
password:1234567890driver-class-name: com.mysql.cj.jdbc.Driver
这样就实现了应用启动时自动将配置文件中的数据源配置读取并生成数据源注册到上下文中;
当然也可以有其他的实现,比如从数据库读取并配置,或者通过接口请求的方式生成都可以,只要实现自己的
DataSourceProvider
就可以。
版权归原作者 后端码匠 所有, 如有侵权,请联系我们删除。