springboot配置多數(shù)據(jù)源的一款框架(dynamic-datasource-spring-boot-starter)
前言
前篇博客介紹了用基本的方式做多數(shù)據(jù)源,可以應(yīng)對(duì)一般的情況,但是遇到一些復(fù)雜的情況就需要擴(kuò)展下功能了,比如:動(dòng)態(tài)增減數(shù)據(jù)源、數(shù)據(jù)源分組,純粹多庫(kù),讀寫分離一主多從,從其他數(shù)據(jù)庫(kù)或者配置中心讀取數(shù)據(jù)源等等。其實(shí)就算沒(méi)有這些需求,使用此款框架實(shí)現(xiàn)多數(shù)據(jù)源也比之前要便捷,快速的多
框架簡(jiǎn)介
dynamic-datasource-spring-boot-starter 是一個(gè)基于 springboot 的快速集成多數(shù)據(jù)源的啟動(dòng)器
文檔:https://github.com/baomidou/dynamic-datasource-spring-boot-starter
文檔:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter
它跟 mybatis-plus 是一個(gè)生態(tài)圈里的,都是由苞米豆團(tuán)隊(duì)出品,很容易集成 mybatis-plus
基本使用
框架說(shuō)明
- 本框架只做
切換數(shù)據(jù)源這件核心的事情,并不限制你的具體操作,切換了數(shù)據(jù)源可以做任何CRUD - 配置文件所有以下劃線
_分割的數(shù)據(jù)源首部即為組的名稱,相同組名稱的數(shù)據(jù)源會(huì)放在一個(gè)組下 - 切換數(shù)據(jù)源可以是組名,也可以是具體數(shù)據(jù)源名稱。組名則切換時(shí)采用負(fù)載均衡算法切換
- 默認(rèn)的數(shù)據(jù)源名稱為
master,你可以通過(guò)spring.datasource.dynamic.primary修改 - 方法上的注解優(yōu)先于類上注解
DS支持繼承抽象類上的DS,暫不支持繼承接口上的DS
與 springboot 的整合
數(shù)據(jù)準(zhǔn)備
-
springboot版本:2.0.6.RELEASE mysql版本:5.7
分別創(chuàng)建數(shù)據(jù)庫(kù) test1,test2,數(shù)據(jù)庫(kù)表均為 goods,數(shù)據(jù)不相同
CREATE TABLE `goods` ( `goodsId` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `goodsName` varchar(500) NOT NULL DEFAULT '' COMMENT 'name', `subject` varchar(200) NOT NULL DEFAULT '' COMMENT '標(biāo)題', `price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '價(jià)格', `stock` int(11) NOT NULL DEFAULT '0' COMMENT 'stock', PRIMARY KEY (`goodsId`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
test1 數(shù)據(jù)庫(kù)數(shù)據(jù)如下

test2 數(shù)據(jù)庫(kù)數(shù)據(jù)如下

引入依賴
至于其他依賴,不再贅述
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.3.2</version> </dependency>
springboot 配置文件
配置文件詳情可以參考官方文檔
server.port=8080 #設(shè)置test1為主數(shù)據(jù)源 spring.datasource.dynamic.primary=master #test1主數(shù)據(jù)源配置 spring.datasource.dynamic.datasource.master.url=jdbc:mysql://127.0.0.1:3306/test1?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC spring.datasource.dynamic.datasource.master.username=root spring.datasource.dynamic.datasource.master.password=123456 spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver spring.datasource.dynamic.datasource.master.type=com.alibaba.druid.pool.DruidDataSource #druid連接池配置 spring.datasource.dynamic.datasource.master.druid.initial-size=5 spring.datasource.dynamic.datasource.master.druid.max-active=20 spring.datasource.dynamic.datasource.master.druid.min-idle=5 spring.datasource.dynamic.datasource.master.druid.max-wait=60000 #test2從數(shù)據(jù)源配置 spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://127.0.0.1:3306/test2?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC spring.datasource.dynamic.datasource.slave.username=root spring.datasource.dynamic.datasource.slave.password=123456 spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.jdbc.Driver spring.datasource.dynamic.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource #druid連接池配置 spring.datasource.dynamic.datasource.slave.druid.initial-size=5 spring.datasource.dynamic.datasource.slave.druid.max-active=20 spring.datasource.dynamic.datasource.slave.druid.min-idle=5 spring.datasource.dynamic.datasource.slave.druid.max-wait=60000 #mybatis配置 mybatis.mapper-locations=classpath:org/example/mapper/*.xml mybatis.configuration.cache-enabled=true #開啟駝峰命名 mybatis.configuration.map-underscore-to-camel-case=true #打印SQL mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
啟動(dòng)類
需要排除掉 DruidDataSourceAutoConfigure 類,不然啟動(dòng)會(huì)報(bào)錯(cuò)找不到配置的 url
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@Slf4j
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
log.info("------springboot running-----");
}
}
實(shí)體類
@Data
@ApiModel
public class Goods implements Serializable {
@ApiModelProperty(value = "商品id")
private Long goodsid;
@ApiModelProperty(value = "商品名稱")
@NotBlank(message = "商品名稱不能為空")
private String goodsname;
@ApiModelProperty(value = "商品描述")
@NotBlank(message = "商品描述不能為空")
private String subject;
@ApiModelProperty(value = "商品價(jià)格")
@NotNull(message = "商品價(jià)格不能為空")
private BigDecimal price;
@ApiModelProperty(value = "商品庫(kù)存", example = "0")
@NotNull(message = "商品庫(kù)存不能為空")
private Integer stock;
}
service 層
至于 dao 層,使用的是 mybatis-generator 插件自動(dòng)生成
@Service
public class GoodServiceImpl implements GoodService {
@Autowired
private GoodsMapper goodsMapper;
@Override
public Goods selectOneGoods(Long goodsid) {
return goodsMapper.selectByPrimaryKey(goodsid);
}
@Override
public int addGoods(Goods goods) {
return goodsMapper.insertSelective(goods);
}
}
controller 層
@Controller
@RequestMapping(path = "/goods")
@Api(tags = "商品管理相關(guān)接口")
@Slf4j
public class GoodsController {
@Autowired
private GoodService goodService;
@GetMapping(path = "/selectOne")
@ResponseBody
@ApiOperation(value = "查詢商品接口")
@ApiImplicitParam(name = "id", value = "商品id", required = true)
public ResultMap selectOne(@RequestParam(name = "id", defaultValue = "3") Long goodsid) {
Goods goods = goodService.selectOneGoods(goodsid);
log.info("查詢到的商品數(shù)據(jù):" + goods.toString());
if (StringUtils.isEmpty(goods)) {
return new ResultMap().fail().message("查詢失敗,沒(méi)有您要的數(shù)據(jù)");
}
return new ResultMap().success().message("查詢成功").data(goods);
}
@PostMapping(path = "/addGoods")
@ResponseBody
@ApiOperation(value = "添加商品的接口")
public ResultMap addGoods(@Valid Goods goods, @NotNull BindingResult bindingResult) {
if (bindingResult.hasErrors()){
String defaultMessage = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
return new ResultMap().fail().message(defaultMessage);
}
int i = goodService.addGoods(goods);
if (i > 0) {
return new ResultMap().success().message("添加成功");
}
return new ResultMap().fail().message("添加失敗");
}
}
測(cè)試
service 層方法上都沒(méi)有注解 @DS
使用 postman 測(cè)試第一個(gè)接口

使用 postman 測(cè)試第二個(gè)接口


以上兩個(gè)接口測(cè)試說(shuō)明:它們都默認(rèn)操作的是主數(shù)據(jù)源 test1,證明我們配置文件中配置的主數(shù)據(jù)源 test1 是配置正確的,已經(jīng)生效
service 層方法上加上注解 @DS 再測(cè)試
@Service
public class GoodServiceImpl implements GoodService {
@Autowired
private GoodsMapper goodsMapper;
@DS(value = "slave")// 切換數(shù)據(jù)源,并指定要訪問(wèn)的數(shù)據(jù)庫(kù)名稱
@Override
public Goods selectOneGoods(Long goodsid) {
return goodsMapper.selectByPrimaryKey(goodsid);
}
@Override
public int addGoods(Goods goods) {
return goodsMapper.insertSelective(goods);
}
}
使用 postman 測(cè)試第一個(gè)接口

此時(shí) @DS 注解已生效,發(fā)生了數(shù)據(jù)源的動(dòng)態(tài)切換
使用 postman 測(cè)試第二個(gè)接口


由于該接口沒(méi)有 @DS 注解,所以沒(méi)有發(fā)生數(shù)據(jù)源的切換,依然操作的是 test1 默認(rèn)數(shù)據(jù)源
@DS 注解說(shuō)明
| 注解 | 結(jié)果 |
|---|---|
| 沒(méi)有@DS | 默認(rèn)數(shù)據(jù)源 |
| @DS("dsName") | dsName可以為組名也可以為具體某個(gè)庫(kù)的名稱 |
- @DS 可以注解在方法上或類上,同時(shí)存在就近原則 方法上注解 優(yōu)先于 類上注解
- @DS 官方建議使用在 service 層的方法上
該框架更詳細(xì)的分析:http://www.dhdzp.com/article/222550.htm
項(xiàng)目源碼:https://gitee.com/chaojiangcj/springboot-dynamic-datasource
到此這篇關(guān)于springboot配置多數(shù)據(jù)源的一款框架的文章就介紹到這了,更多相關(guān)springboot多數(shù)據(jù)源配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot項(xiàng)目如何配置多數(shù)據(jù)源
- SpringBoot實(shí)現(xiàn)JPA多數(shù)據(jù)源配置小結(jié)
- SpringBoot實(shí)現(xiàn)多數(shù)據(jù)源配置的示例詳解
- SpringBoot中實(shí)現(xiàn)多數(shù)據(jù)源連接和切換的方案
- 淺析SpringBoot多數(shù)據(jù)源實(shí)現(xiàn)方案
- springboot項(xiàng)目實(shí)現(xiàn)多數(shù)據(jù)源配置使用dynamic-datasource-spring-boot-starter的操作步驟
- SpringBoot利用dynamic-datasource-spring-boot-starter解決多數(shù)據(jù)源問(wèn)題
相關(guān)文章
mybatis實(shí)現(xiàn)mapper代理模式的方式
本文向大家講解mybatis的mapper代理模式,以根據(jù)ide值查詢單條數(shù)據(jù)為例編寫xml文件,通過(guò)mapper代理的方式進(jìn)行講解增刪改查,分步驟給大家講解的很詳細(xì),對(duì)mybatis mapper代理模式相關(guān)知識(shí)感興趣的朋友一起看看吧2021-06-06
Java中IO流 RandomAccessFile類實(shí)例詳解
這篇文章主要介紹了Java中IO流 RandomAccessFile類實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05
關(guān)于Java8中map()和flatMap()的一些事
這篇文章主要給大家介紹了關(guān)于Java8中map()和flatMap()的一些事,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java排序之Comparable和Comparator比較器詳解
這篇文章主要介紹了Java排序之Comparable和Comparator比較器詳解,Comparable<T>是內(nèi)部比較器,Comparator<T>是外部比較器,最推薦使用Comparator<T>接口排序,Comparator提供靜態(tài)方法很方便,推薦使用,需要的朋友可以參考下2024-01-01
Java中LinkedHashSet、LinkedHashMap源碼詳解
這篇文章主要介紹了Java中LinkedHashSet、LinkedHashMap源碼詳解,LinkedHashMap是一個(gè)以雙向鏈表的方式將Entry節(jié)點(diǎn)鏈接起來(lái)的HashMap子類,它在HashMap的基礎(chǔ)上實(shí)現(xiàn)了更多的功能,具有順序存儲(chǔ)和遍歷的特性,需要的朋友可以參考下2023-09-09

