0.前言
上一篇文章我們講了如何通過多數(shù)據(jù)源組件,在Spring boot Druid 連接池項目中配置多數(shù)據(jù)源,并且通過@DS注解的方式切換數(shù)據(jù)源,《Spring Boot 配置多數(shù)據(jù)源【最簡單的方式】》。但是在多租戶的業(yè)務(wù)場景中,我們通常需要手動的切換數(shù)據(jù)源,那么本文將解答你的額疑惑。
1. 動態(tài)添加移除數(shù)據(jù)源
dynamic-datasource是一款基于Spring Boot 動態(tài)數(shù)據(jù)源框架,在應(yīng)用程序運行時可以動態(tài)添加、移除數(shù)據(jù)源的功能。
2.基礎(chǔ)介紹
本文我們還是以dynamic-datasource來進階學習。提供了一系列的API和配置項,可以非常方便地實現(xiàn)動態(tài)添加、移除數(shù)據(jù)源的功能。本文將介紹如何使用dynamic-datasource動態(tài)添加、移除數(shù)據(jù)源,并對相關(guān)代碼進行解析。在多租戶應(yīng)用、讀寫分離等場景下,動態(tài)數(shù)據(jù)源可以方便地實現(xiàn)數(shù)據(jù)源的動態(tài)切換,提高應(yīng)用程序的靈活性和擴展性。
主要在多租戶場景中,常常新的一個租戶進來需要動態(tài)的添加一個數(shù)據(jù)源到庫中,使得系統(tǒng)不用重啟即可切換數(shù)據(jù)源。
3. 使用步驟示例
dynamic-datasource 3.4.0及以上版本和老版本注入方式有一定差別,根據(jù)自己版本注入。
注意一定要讓多數(shù)據(jù)源使用 @Primary ,讓其成為主數(shù)據(jù)源。
簡單示例,自己手動構(gòu)造dataSource
//3.4.0版本以下
@Primary
@Bean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
//3.4.0版本及以上
@Primary
@Bean
public DataSource dataSource() {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
主要變更是因為3.4.0支持了多個provider同時生效,采取了內(nèi)部注入。 源碼改動參考
https://github.com/baomidou/dynamic-datasource-spring-boot-starter/commit/6e8d2954499f83269302d23b58f8832c31e07ef7
復雜示例,使用DataSourceCreator構(gòu)造dataSource
本文我們還是以dynamic-datasource來進階學習。提供了一系列的API和配置項,可以非常方便地實現(xiàn)動態(tài)添加、移除數(shù)據(jù)源的功能。本文將介紹如何使用dynamic-datasource動態(tài)添加、移除數(shù)據(jù)源,并對相關(guān)代碼進行解析。在多租戶應(yīng)用、讀寫分離等場景下,動態(tài)數(shù)據(jù)源可以方便地實現(xiàn)數(shù)據(jù)源的動態(tài)切換,提高應(yīng)用程序的靈活性和擴展性。
主要在多租戶場景中,常常新的一個租戶進來需要動態(tài)的添加一個數(shù)據(jù)源到庫中,使得系統(tǒng)不用重啟即可切換數(shù)據(jù)源。
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.*;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.samples.ds.dto.DataSourceDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.sql.DataSource;
import java.util.Set;
@RestController
@RequestMapping("/datasources")
@Api(tags = "添加刪除數(shù)據(jù)源")
public class DataSourceController {
@Autowired
private DataSource dataSource;
// private final DataSourceCreator dataSourceCreator; //3.3.1及以下版本使用這個通用,強烈推薦sb2用戶至少升級到3.5.2版本
@Autowired
private DefaultDataSourceCreator dataSourceCreator;
//如果是用4.x以上版本,因為要和spring解綁,重構(gòu)了一些東西,比如缺少了懶啟動和啟動初始化數(shù)據(jù)庫。不太建議用以下獨立的創(chuàng)建器,只建議用上面的DefaultDataSourceCreator
@Autowired
private BasicDataSourceCreator basicDataSourceCreator;
@Autowired
private JndiDataSourceCreator jndiDataSourceCreator;
@Autowired
private DruidDataSourceCreator druidDataSourceCreator;
@Autowired
private HikariDataSourceCreator hikariDataSourceCreator;
@Autowired
private BeeCpDataSourceCreator beeCpDataSourceCreator;
@Autowired
private Dbcp2DataSourceCreator dbcp2DataSourceCreator;
@GetMapping
@ApiOperation("獲取當前所有數(shù)據(jù)源")
public Set<String> now() {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
return ds.getDataSources().keySet();
}
//通用數(shù)據(jù)源會根據(jù)maven中配置的連接池根據(jù)順序依次選擇。
//默認的順序為druid>hikaricp>beecp>dbcp>spring basic
@PostMapping("/add")
@ApiOperation("通用添加數(shù)據(jù)源(推薦)")
public Set<String> add(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPoolName(), dataSource);
return ds.getDataSources().keySet();
}
@PostMapping("/addBasic(強烈不推薦,除了用了馬上移除)")
@ApiOperation(value = "添加基礎(chǔ)數(shù)據(jù)源", notes = "調(diào)用Springboot內(nèi)置方法創(chuàng)建數(shù)據(jù)源,兼容1,2")
public Set<String> addBasic(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = basicDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPoolName(), dataSource);
return ds.getDataSources().keySet();
}
@PostMapping("/addJndi")
@ApiOperation("添加JNDI數(shù)據(jù)源")
public Set<String> addJndi(String pollName, String jndiName) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = jndiDataSourceCreator.createDataSource(jndiName);
ds.addDataSource(poolName, dataSource);
return ds.getDataSources().keySet();
}
@PostMapping("/addDruid")
@ApiOperation("基礎(chǔ)Druid數(shù)據(jù)源")
public Set<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
dataSourceProperty.setLazy(true);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPoolName(), dataSource);
return ds.getDataSources().keySet();
}
@PostMapping("/addHikariCP")
@ApiOperation("基礎(chǔ)HikariCP數(shù)據(jù)源")
public Set<String> addHikariCP(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
dataSourceProperty.setLazy(true);//3.4.0版本以下如果有此屬性,需手動設(shè)置,不然會空指針。
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPoolName(), dataSource);
return ds.getDataSources().keySet();
}
@PostMapping("/addBeeCp")
@ApiOperation("基礎(chǔ)BeeCp數(shù)據(jù)源")
public Set<String> addBeeCp(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
dataSourceProperty.setLazy(true);//3.4.0版本以下如果有此屬性,需手動設(shè)置,不然會空指針。
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = beeCpDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPoolName(), dataSource);
return ds.getDataSources().keySet();
}
@PostMapping("/addDbcp")
@ApiOperation("基礎(chǔ)Dbcp數(shù)據(jù)源")
public Set<String> addDbcp(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
dataSourceProperty.setLazy(true);//3.4.0版本以下如果有此屬性,需手動設(shè)置,不然會空指針。
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = dbcp2DataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPoolName(), dataSource);
return ds.getDataSources().keySet();
}
@DeleteMapping
@ApiOperation("刪除數(shù)據(jù)源")
public String remove(String name) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
ds.removeDataSource(name);
return "刪除成功";
}
}
4. 示例項目
https://github.com/dynamic-datasource/dynamic-datasource-samples/tree/master/features-samples/add-remove-datasource-sample文章來源:http://www.zghlxwxcb.cn/news/detail-647852.html
5. 源碼分析
public interface DataSourceCreator {
/**
* 通過屬性創(chuàng)建數(shù)據(jù)源
*
* @param dataSourceProperty 數(shù)據(jù)源屬性
* @return 被創(chuàng)建的數(shù)據(jù)源
*/
DataSource createDataSource(DataSourceProperty dataSourceProperty);
/**
* 當前創(chuàng)建器是否支持根據(jù)此屬性創(chuàng)建
*
* @param dataSourceProperty 數(shù)據(jù)源屬性
* @return 是否支持
*/
boolean support(DataSourceProperty dataSourceProperty);
}
DataSourceCreator是一個接口,定義了根據(jù)參數(shù)創(chuàng)建數(shù)據(jù)源的接口。
其他creator實現(xiàn)此接口,本項目暫時實現(xiàn)了Druid和Hikaricp的等連接池的實現(xiàn)。
BasicDataSourceCreator 是調(diào)用Spring原生的創(chuàng)建方式,只支持最最原始的基礎(chǔ)配置。
DefaultDataSourceCreator 是一個通用的創(chuàng)建器,其根據(jù)環(huán)境自動選擇連接池,文章來源地址http://www.zghlxwxcb.cn/news/detail-647852.html
到了這里,關(guān)于Springboot 多數(shù)據(jù)源 dynamic-datasource動態(tài)添加移除數(shù)據(jù)源的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!