激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 談談Spring Boot 數據源加載及其多數據源簡單實現(小結)

談談Spring Boot 數據源加載及其多數據源簡單實現(小結)

2021-07-31 12:29冷冷 Java教程

這篇文章主要介紹了談談Spring Boot 數據源加載及其多數據源簡單實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

業(yè)務需求

  • 提供所有微服務數據源的圖形化維護功能
  • 代碼生成可以根據選擇的數據源加載表等源信息
  • 數據源管理要支持動態(tài)配置,實時生效

附錄效果圖

談談Spring Boot 數據源加載及其多數據源簡單實現(小結)

談談Spring Boot 數據源加載及其多數據源簡單實現(小結)

實現思路

本文提供方法僅供類似簡單業(yè)務場景,在生產環(huán)境和復雜的業(yè)務場景 請使用分庫分表的中間件(例如mycat)或者框架 sharding-sphere (一直在用)等

先來看spring 默認的數據源注入策略,如下代碼默認的事務管理器在初始化時回去加載數據源實現。這里就是我們動態(tài)數據源的入口

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 默認的事務管理器
ppublic class datasourcetransactionmanager extends abstractplatformtransactionmanager
  implements resourcetransactionmanager, initializingbean {
 
 // 啟動時候注入一個數據源
 public void setdatasource(@nullable datasource datasource) {
  if (datasource instanceof transactionawaredatasourceproxy) {
   this.datasource = ((transactionawaredatasourceproxy) datasource).gettargetdatasource();
  }
  else {
   this.datasource = datasource;
  }
 }

通過注入一個新的datasourcetransactionmanager 實現,并且給它設置多個 datasource 來實現多數據源實現

談談Spring Boot 數據源加載及其多數據源簡單實現(小結)

看下spring 默認提供的路由數據源字段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class abstractroutingdatasource extends abstractdatasource implements initializingbean {
 
 // 用戶設置的全部的數據源配置
 @nullable
 private map<object, object> targetdatasources;
 // 為空默認的數據源配置
 @nullable
 private object defaulttargetdatasource;
 
 // 路由鍵查找實現
 private datasourcelookup datasourcelookup = new jndidatasourcelookup();
 
 // 最終有效的數據源配置(一般清空對應上邊用戶的設置)
 @nullable
 private map<object, datasource> resolveddatasources;
}

開始動手

實現abstractroutingdatasource,定一個動態(tài)數據源實現,只需要實現他的路由key 查找方法即可。

這里的路由key 對應其實是resolveddatasources map 的key喲

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@slf4j
public class dynamicdatasource extends abstractroutingdatasource {
 
 /**
  * 指定路由key,這里很簡單 獲取 threadlocal 中目標key 即可
  *
  * @return
  */
 @override
 protected object determinecurrentlookupkey() {
  return dynamicdatasourcecontextholder.getdatasourcetype();
 }
}

把我們動態(tài)數據源實現注入到spring 的事務管理器,去數據庫查詢出來全部的數據源信息,定義一個個具體的數據源實現 我這里使用的hikaridatasource 給他賦值等等

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@slf4j
@configuration
@allargsconstructor
public class dynamicdatasourceconfig implements transactionmanagementconfigurer {
 private final map<object, object> datasourcemap = new hashmap<>(8);
 private final datasourceproperties datasourceproperties;
 
 @bean("dynamicdatasource")
 public dynamicdatasource datasource() {
  jdbctemplate(dds).queryforlist(datasourceconstant.query_ds_sql);
  log.info("開始 -> 初始化動態(tài)數據源");
  optional.of(dblist).ifpresent(list -> list.foreach(db -> {
   log.info("數據源:{}", db.get(datasourceconstant.ds_name));
   hikaridatasource ds = new hikaridatasource();
   datasourcemap.put(db.get(datasourceconstant.ds_route_key), ds);
  }));
  
  dynamicdatasource ds = new dynamicdatasource();
  ds.settargetdatasources(datasourcemap);
  return ds;
 }
 
 @bean
 public platformtransactionmanager txmanager() {
  return new datasourcetransactionmanager(datasource());
 }
 
 @override
 public platformtransactionmanager annotationdriventransactionmanager() {
  return txmanager();
 }
 
}

怎么使用

只需要根據用戶前臺選擇的數據源key ,在業(yè)務類保存到ttl 即可,會自動根據選擇路由數據源

?
1
dynamicdatasourcecontextholder.setdatasourcetype(key)

這里當然也可以根據aop 自定義注解等實現。

如何動態(tài)數據源動態(tài)配置

上邊其實已經完成了 我們想要的需求功能,但是有什么問題呢?
我們在數據源管理面維護了數據源,動態(tài)去修改這個 datasourcemap 其實是無效的,不能做到實時刷新

我們來看下 abstractroutingdatasource 的加載map 數據源的源碼,只有在初始化的時候調用 afterpropertiesset 去初始數據源map.

談談Spring Boot 數據源加載及其多數據源簡單實現(小結)

那我們只要獲取當前的dynamicdatasource bean 手動調用afterpropertiesset 即可。

整個代碼如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class dynamicdatasourceconfig implements transactionmanagementconfigurer {
 private final map<object, object> datasourcemap = new hashmap<>(8);
 private final datasourceproperties datasourceproperties;
 private final stringencryptor stringencryptor;
 
 @bean("dynamicdatasource")
 public dynamicdatasource datasource() {
  dynamicdatasource ds = new dynamicdatasource();
  hikaridatasource cads = new hikaridatasource();
  cads.setjdbcurl(datasourceproperties.geturl());
  cads.setdriverclassname(datasourceproperties.getdriverclassname());
  cads.setusername(datasourceproperties.getusername());
  cads.setpassword(datasourceproperties.getpassword());
  ds.setdefaulttargetdatasource(cads);
  datasourcemap.put(0, cads);
  ds.settargetdatasources(datasourcemap);
  return ds;
 }
 
 /**
  * 組裝默認配置的數據源,查詢數據庫配置
  */
 @postconstruct
 public void init() {
  drivermanagerdatasource dds = new drivermanagerdatasource();
  dds.seturl(datasourceproperties.geturl());
  dds.setdriverclassname(datasourceproperties.getdriverclassname());
  dds.setusername(datasourceproperties.getusername());
  dds.setpassword(datasourceproperties.getpassword());
 
  list<map<string, object>> dblist = new jdbctemplate(dds).queryforlist(datasourceconstant.query_ds_sql);
  log.info("開始 -> 初始化動態(tài)數據源");
  optional.of(dblist).ifpresent(list -> list.foreach(db -> {
   log.info("數據源:{}", db.get(datasourceconstant.ds_name));
   hikaridatasource ds = new hikaridatasource();
   ds.setjdbcurl(string.valueof(db.get(datasourceconstant.ds_jdbc_url)));
   ds.setdriverclassname(driver.class.getname());
   ds.setusername((string) db.get(datasourceconstant.ds_user_name));
 
   string decpwd = stringencryptor.decrypt((string) db.get(datasourceconstant.ds_user_pwd));
   ds.setpassword(decpwd);
   datasourcemap.put(db.get(datasourceconstant.ds_route_key), ds);
  }));
 
  log.info("完畢 -> 初始化動態(tài)數據源,共計 {} 條", datasourcemap.size());
 }
 
 /**
  * 重新加載數據源配置
  */
 public boolean reload() {
  init();
  dynamicdatasource datasource = datasource();
  datasource.settargetdatasources(datasourcemap);
  datasource.afterpropertiesset();
  return boolean.false;
 }
 
 
 @bean
 public platformtransactionmanager txmanager() {
  return new datasourcetransactionmanager(datasource());
 }
 
 @override
 public platformtransactionmanager annotationdriventransactionmanager() {
  return txmanager();
 }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://segmentfault.com/a/1190000018844625

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 激情视频导航 | 97香蕉超级碰碰久久免费软件 | 亚洲午夜一区二区三区 | 色偷偷欧美 | 久久精品亚洲国产奇米99 | 日韩毛片毛片久久精品 | 黄色网址入口 | 欧美一级黄色片免费观看 | 中文字幕专区高清在线观看 | caoporn国产一区二区 | 毛片视频观看 | 久久久久久久久久久av | 中文欧美日韩 | av中文在线观看 | 精品一区二区三区毛片 | 毛片免费视频网站 | 国语自产免费精品视频在 | 免费一级欧美大片视频 | 午夜精品一区二区三区免费 | 亚洲成人中文字幕在线 | 欧美一级一区二区三区 | 亚卅毛片| 亚洲成人免费影视 | 好吊色欧美一区二区三区四区 | 国产一区视频在线免费观看 | 日日狠狠久久偷偷四色综合免费 | 欧美一区二区三区免费电影 | 毛片在线免费视频 | 久久在线免费视频 | 久久在线| 第四色成人网 | 精品一区二区三区免费看 | 久久99精品国产自在现线 | 九九看片 | 亚洲国产中文字幕 | 欧日韩在线 | 小视频成人 | 午夜视频在线免费播放 | 欧美大穴 | 中文字幕一区二区三区久久 | 粉嫩av一区二区三区四区在线观看 |