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

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

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

服務器之家 - 編程語言 - Java教程 - spring boot+mybatis 多數據源切換(實例講解)

spring boot+mybatis 多數據源切換(實例講解)

2021-01-03 15:25易興 Java教程

下面小編就為大家帶來一篇spring boot+mybatis 多數據源切換(實例講解)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

由于公司業務劃分了多個數據庫,開發一個項目會同事調用多個庫,經過學習我們采用了注解+aop的方式實現的

1.首先定義一個注解類

?
1
2
3
4
5
@retention(retentionpolicy.runtime)
@target(elementtype.method)
public @interface targetdatasource {
 string value();//此處接收的是數據源的名稱
}

2.然后建一個配置類,這個在項目啟動時會加載數據源,一開始采用了hikaricp,查資料說是最快性能最好的,然后又發現了阿里的druid,這個功能比較全面,而且性能也還可以,最主要他還有監控功能,具體實現看如下代碼

?
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package com.example.demo.datasource;
 
import com.alibaba.druid.pool.druiddatasource;
import com.alibaba.druid.support.http.statviewservlet;
import com.alibaba.druid.support.http.webstatfilter;
import com.example.demo.datasource.dynamicdatasource;
import com.zaxxer.hikari.hikariconfig;
import com.zaxxer.hikari.hikaridatasource;
import lombok.extern.slf4j.slf4j;
import org.mybatis.spring.annotation.mapperscan;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.beans.factory.annotation.qualifier;
import org.springframework.beans.factory.annotation.value;
import org.springframework.boot.web.servlet.filterregistrationbean;
import org.springframework.boot.web.servlet.servletregistrationbean;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.jdbc.datasource.datasourcetransactionmanager;
import org.springframework.scheduling.annotation.enablescheduling;
import org.springframework.scheduling.annotation.scheduled;
import org.springframework.transaction.platformtransactionmanager;
import org.w3c.dom.nodelist;
import org.w3c.dom.document;
import org.w3c.dom.element;
import org.w3c.dom.node;
 
import javax.servlet.annotation.webinitparam;
import javax.servlet.annotation.webservlet;
import javax.sql.datasource;
import javax.xml.parsers.documentbuilder;
import javax.xml.parsers.documentbuilderfactory;
import java.lang.reflect.field;
import java.lang.reflect.method;
import java.util.hashmap;
import java.util.map;
import java.io.file;
import com.alibaba.druid.support.http.statviewservlet;
/**
 * author: wangchao
 * version:
 * date:  2017/9/11
 * description:數據源配置
 * modification history:
 * date    author    version   description
 * --------------------------------------------------------------
 * why & what is modified:
 */
 
@configuration
@enablescheduling
public class datasourceconfig {
 
 /*@autowired
 private dbproperties properties;*/
 @value("${datasource.filepath}")
 private string filepath;//數據源配置
 
 @bean(name = "datasource")
 public datasource datasource() {
  //按照目標數據源名稱和目標數據源對象的映射存放在map中
  map<object, object> targetdatasources = new hashmap<>();
  //查找xml數據連接字符串
  targetdatasources=getdatamap(filepath);
  //動態獲取dbproperties類申明的屬性
  /*field[] fields=properties.getclass().getdeclaredfields();
  for(int i=0;i<fields.length;i++)
  {
   targetdatasources.put(fields[i].getname(), getfieldvaluebyname(fields[i].getname(),properties));
  }*/
  //采用是想abstractroutingdatasource的對象包裝多數據源
  dynamicdatasource datasource = new dynamicdatasource();
  datasource.settargetdatasources(targetdatasources);
  //設置默認的數據源,當拿不到數據源時,使用此配置
  //datasource.setdefaulttargetdatasource(properties.getuzaitravel());
  return datasource;
 }
 
 @bean
 public platformtransactionmanager txmanager() {
  return new datasourcetransactionmanager(datasource());
 }
 
 /**
 *獲取數據源集合
 */
 
 private map<object, object> getdatamap(string fiepath)
 {
 
  try {
   map<object, object> targetdatasources = new hashmap<>();
   file xmlfile = new file(fiepath);
 
   documentbuilderfactory builderfactory = documentbuilderfactory.newinstance();
 
   documentbuilder builder = builderfactory.newdocumentbuilder();
 
   document doc = builder.parse(xmlfile);
 
   doc.getdocumentelement().normalize();
 
   system.out.println("root element: " + doc.getdocumentelement().getnodename());
 
   nodelist nlist = doc.getelementsbytagname("db");
   for(int i = 0 ; i<nlist.getlength();i++) {
 
    node node = nlist.item(i);
    element ele = (element)node;
 
    /*hikariconfig config = new hikariconfig();
    config.setdriverclassname(ele.getelementsbytagname("driver-class").item(0).gettextcontent());
    config.setjdbcurl(ele.getelementsbytagname("jdbc-url").item(0).gettextcontent());
    config.setusername(ele.getelementsbytagname("username").item(0).gettextcontent());
    config.setpassword(ele.getelementsbytagname("password").item(0).gettextcontent());
    //config.adddatasourceproperty("password", ele.getelementsbytagname("password").item(0).gettextcontent());
    hikaridatasource datasource = new hikaridatasource(config);*/
 
 
    druiddatasource datasource = new druiddatasource();
    datasource.setdriverclassname(ele.getelementsbytagname("driver-class").item(0).gettextcontent());
    datasource.setusername(ele.getelementsbytagname("username").item(0).gettextcontent());
    datasource.setpassword(ele.getelementsbytagname("password").item(0).gettextcontent());
    datasource.seturl(ele.getelementsbytagname("jdbc-url").item(0).gettextcontent());
    datasource.setinitialsize(5);
    datasource.setminidle(1);
    datasource.setmaxactive(10);// 啟用監控統計功能
    datasource.setfilters("stat");//設置是否顯示sql語句
    targetdatasources.put(ele.getelementsbytagname("databasename").item(0).gettextcontent(), datasource);
   }
   return targetdatasources;
  }
  catch (exception ex)
  {
   return null;
  }
 
 }
 //訪問的ip
 @value("${druid.ip}")
 private string ip;
 //登錄名
 @value("${druid.druidlgoinname}")
 private string druidlgoinname;
 //密碼
 @value("${druid.druidlgoinpassword}")
 private string druidlgoinpassword;
 
 @bean
 public servletregistrationbean druidstatviewservle() {
  //org.springframework.boot.context.embedded.servletregistrationbean提供類的進行注冊.
  servletregistrationbean servletregistrationbean = new servletregistrationbean(new statviewservlet(), "/druid/*");
  //添加初始化參數:initparams
 
  //白名單:
  servletregistrationbean.addinitparameter("allow",ip);
  //ip黑名單 (存在共同時,deny優先于allow) : 如果滿足deny的話提示:sorry, you are not permitted to view this page.
  // servletregistrationbean.addinitparameter("deny", "192.168.1.73");
  //登錄查看信息的賬號密碼.
  servletregistrationbean.addinitparameter("loginusername",druidlgoinname);
  servletregistrationbean.addinitparameter("loginpassword",druidlgoinpassword);
  //是否能夠重置數據.
  servletregistrationbean.addinitparameter("resetenable","false");
  return servletregistrationbean;
 }
 
 /**
 
  * 注冊一個:filterregistrationbean
 
  * @return
 
 */
 @bean
 public filterregistrationbean druidstatfilter2(){
  filterregistrationbean filterregistrationbean = new filterregistrationbean(new webstatfilter());
  //添加過濾規則.
  filterregistrationbean.addurlpatterns("/*");
  //添加不需要忽略的格式信息.
  filterregistrationbean.addinitparameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
  return filterregistrationbean;
 }
 
}

3.動態數據源,從之前已加載的數據源中選取,dynamicdatasource和dynamicdatasourceholder配合使用

?
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
public class dynamicdatasource extends abstractroutingdatasource{
 //數據源路由,此方用于產生要選取的數據源邏輯名稱
 @override
 protected object determinecurrentlookupkey() {
  //從共享線程中獲取數據源名稱
  return dynamicdatasourceholder.getdatasource();
 }
}
 
public class dynamicdatasourceholder {
 /**
  * 本地線程共享對象
  */
 private static final threadlocal<string> thread_local = new threadlocal<>();
 
 public static void putdatasource(string name) {
  thread_local.set(name);
 }
 
 public static string getdatasource() {
  return thread_local.get();
 }
 
 public static void removedatasource() {
  thread_local.remove();
 }
}

4.就是使用aop,在dao層切換數據源

?
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
@component
@aspect
public class datasourceaspect {
 //切換放在mapper接口的方法上,所以這里要配置aop切面的切入點
 @pointcut("execution( * com.example.demo.dao.*.*(..))")
 public void datasourcepointcut() {
 }
 
 @before("datasourcepointcut()")
 public void before(joinpoint joinpoint) {
  object target = joinpoint.gettarget();
  string method = joinpoint.getsignature().getname();
  class<?>[] clazz = target.getclass().getinterfaces();
  class<?>[] parametertypes = ((methodsignature) joinpoint.getsignature()).getmethod().getparametertypes();
  try {
   method m = clazz[0].getmethod(method, parametertypes);
   //如果方法上存在切換數據源的注解,則根據注解內容進行數據源切換
   if (m != null && m.isannotationpresent(targetdatasource.class)) {
    targetdatasource data = m.getannotation(targetdatasource.class);
    string datasourcename = data.value();
    dynamicdatasourceholder.putdatasource(datasourcename);
 
   } else {
 
   }
  } catch (exception e) {
 
  }
 }
 
 //執行完切面后,將線程共享中的數據源名稱清空
 @after("datasourcepointcut()")
 public void after(joinpoint joinpoint){
  dynamicdatasourceholder.removedatasource();
 }
}

數據連接都配置在xml里面spring boot+mybatis 多數據源切換(實例講解)

xml路徑在配置文件里面配置,這樣適用讀寫分離和多個不同的數據源,而且多個項目可以共用這一個配置

spring boot+mybatis 多數據源切換(實例講解)

最后引用注解,需要注意的是注解的數據庫名稱和xml里面databasename節點是一一對應的,可以隨便自定義,比如讀寫是一個數據庫名字,這時候就可以定義成pringtest_r表示讀庫

spring boot+mybatis 多數據源切換(實例講解)

至此多數據源就配置完成,至于阿里的druid下次再分享,代碼都貼出來,如果大家感覺還有哪些不足的地方,歡迎指正。

以上這篇spring boot+mybatis 多數據源切換(實例講解)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/ok123/archive/2017/09/14/7523106.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99ri在线| 亚洲精品久久久久久下一站 | 成人啪啪18免费网站 | 久久精品欧美视频 | 懂色av懂色aⅴ精彩av | 亚洲精品成人在线视频 | 国产精品久久久久久久久久大牛 | 99爱视频在线观看 | 亚洲精品一区二区三区在线看 | 国产精品久久久久久久久久iiiii | 国产一区二区三区影视 | 天天草天天爱 | 亚洲第一成人在线视频 | 撅高 自己扒开 调教 | 久久久久久麻豆 | 国产一区视频在线观看免费 | 欧洲怡红院 | 成人在线视频免费观看 | 农村寡妇偷毛片一级 | 国产a级片电影 | 国产高潮好爽受不了了夜色 | www.91pron| 狠很操 | 91精品片 | 7777在线视频免费播放 | 亚洲午夜免费 | 在线看免费观看日本 | 中文字幕xxx | 久久久久99999 | 91久久久国产精品 | 新久草在线视频 | 欧美一级做一级爱a做片性 久久久资源网 | 国产乱色精品成人免费视频 | 国产一级做a爰片在线看 | 黄色片免费在线播放 | 黄色av电影在线播放 | 欧美一级淫片a免费播放口 91九色蝌蚪国产 | 国产精品一区二区视频 | 美女毛片儿 | 国产羞羞网站 | 久久精品一区二区三区四区五区 |