springboot+aop實(shí)現(xiàn)多數(shù)據(jù)源配置

轉(zhuǎn)載https://www.cnblogs.com/puretuo/p/11365359.html单起;

一. mybatis plus

?因?yàn)槲覀冺?xiàng)目是springboot+mybatis plus仓手,有些人一看搀玖,mybatis還知道對(duì)吧乳幸,mybatis plus是什么鬼怕品,其實(shí)字面意思可以理解治笨,就是對(duì)mybatis進(jìn)行一些功能改造考婴,一些封裝升級(jí),然后用起來(lái)特別方便杆麸。

? ? ?核心功能的升級(jí)主要是以下三點(diǎn):

? ? ?支持通用的 CRUD搁进、代碼生成器與條件構(gòu)造器。

通用 CRUD:定義好 Mapper 接口后昔头,只需要繼承 BaseMapper 接口即可獲得通用的增刪改查功能饼问,無(wú)需編寫任何接口方法與配置文件

條件構(gòu)造器:通過(guò) EntityWrapper (實(shí)體包裝類),可以用于拼接 SQL 語(yǔ)句揭斧,并且支持排序莱革、分組查詢等復(fù)雜的 SQL

代碼生成器:支持一系列的策略配置與全局配置,比 MyBatis 的代碼生成更好用

二.多數(shù)據(jù)源配置開(kāi)始

? ? 思路:

  1讹开、yml中配置多個(gè)數(shù)據(jù)源信息

  2盅视、通過(guò)AOP切換不同數(shù)據(jù)源

  3、配合mybatis plus使用


1旦万、yml配置

spring:

??aop:

??????proxy-target-class:?true

??????auto:?true

??datasource:

????druid:

??????db1:

????????url: jdbc:mysql://localhost:3306/eboot

????????username: root

????????password: root

????????driver-class-name: com.mysql.jdbc.Driver

????????initialSize:?5

????????minIdle:?5

????????maxActive:?20

??????db2:

????????url: jdbc:oracle:thin:@192.168.136.222:ORCL

????????username: sa

????????password: sa123456

????????driver-class-name: oracle.jdbc.OracleDriver

????????initialSize:?5

????????minIdle:?5

????????maxActive:?20

2闹击、啟動(dòng)多個(gè)數(shù)據(jù)源

@EnableTransactionManagement?//開(kāi)啟事務(wù)

@Configuration?//spring中常用到注解,與xml配置相對(duì)立成艘。是兩種加載bean方式

@MapperScan("com.df.openapi.**.mapper.db*")?// 掃描mapperdao的地址

public?class?MybatisPlusConfig {


????@Bean

????public?PaginationInterceptor paginationInterceptor() {

????????PaginationInterceptor paginationInterceptor =?new?PaginationInterceptor();

//??????? paginationInterceptor.setLocalPage(true); // 由于版本問(wèn)題赏半,有些類可能招不到這個(gè)方法,需要升級(jí)jar包

????????return?paginationInterceptor;

????}


????@Bean(name =?"db1")

????@ConfigurationProperties(prefix =?"spring.datasource.druid.db1")

????public?DataSource db1() {

????????return?DruidDataSourceBuilder.create().build();

????}


????@Bean(name =?"db2")

????@ConfigurationProperties(prefix =?"spring.datasource.druid.db2")

????public?DataSource db2() {

????????return?DruidDataSourceBuilder.create().build();

????}


????/**

?????* 動(dòng)態(tài)數(shù)據(jù)源配置

?????*

?????* @return

?????*/

????@Bean

????@Primary

????public?DataSource multipleDataSource(@Qualifier("db1") DataSource db1,

?????????????????????????????????????????@Qualifier("db2") DataSource db2) {

????????DynamicDataSource dynamicDataSource =?new?DynamicDataSource();

????????Map targetDataSources =?new?HashMap<>();

????????targetDataSources.put(DBTypeEnum.db1.getValue(), db1);

????????targetDataSources.put(DBTypeEnum.db2.getValue(), db2);

????????dynamicDataSource.setTargetDataSources(targetDataSources);

????????dynamicDataSource.setDefaultTargetDataSource(db2);?// 程序默認(rèn)數(shù)據(jù)源淆两,這個(gè)要根據(jù)程序調(diào)用數(shù)據(jù)源頻次断箫,經(jīng)常把常調(diào)用的數(shù)據(jù)源作為默認(rèn)

????????return?dynamicDataSource;

????}


????@Bean("sqlSessionFactory")

????public?SqlSessionFactory sqlSessionFactory()?throws?Exception {

????????MybatisSqlSessionFactoryBean sqlSessionFactory =?new?MybatisSqlSessionFactoryBean();

????????sqlSessionFactory.setDataSource(multipleDataSource(db1(), db2()));


????????MybatisConfiguration configuration =?new?MybatisConfiguration();

????????configuration.setJdbcTypeForNull(JdbcType.NULL);

????????configuration.setMapUnderscoreToCamelCase(true);

????????configuration.setCacheEnabled(false);

????????sqlSessionFactory.setConfiguration(configuration);

????????//PerformanceInterceptor(),OptimisticLockerInterceptor()

????????//添加分頁(yè)功能

????????sqlSessionFactory.setPlugins(new?Interceptor[]{

????????????????paginationInterceptor()

????????});

//??????? sqlSessionFactory.setGlobalConfig(globalConfiguration()); //注釋掉全局配置,因?yàn)樵趚ml中讀取就是全局配置

????????return?sqlSessionFactory.getObject();

????}


?/*?? @Bean

????public GlobalConfiguration globalConfiguration() {

????????GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());

????????conf.setLogicDeleteValue("-1");

????????conf.setLogicNotDeleteValue("1");

????????conf.setIdType(0);

????????conf.setMetaObjectHandler(new MyMetaObjectHandler());

????????conf.setDbColumnUnderline(true);

????????conf.setRefresh(true);

????????return conf;

????}*/

}

3秋冰、DBType枚舉類

package?com.df.openapi.config.db;


public?enum?DBTypeEnum {


????db1("db1"), db2("db2");

????private?String value;


????DBTypeEnum(String value) {

????????this.value = value;

????}


????public?String getValue() {

????????return?value;

????}

}

4仲义、動(dòng)態(tài)數(shù)據(jù)源決策

package?com.df.openapi.config.db;

import?org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public?class?DynamicDataSource?extends?AbstractRoutingDataSource {

private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSource.class);

@Override

protected Object determineCurrentLookupKey() {

String datasource = DataSourceContextHolder.getDbType();

LOGGER.debug("使用數(shù)據(jù)源 {}", datasource);

return datasource;

}

}

5、設(shè)置剑勾、獲取數(shù)據(jù)源

public?class?DataSourceContextHolder {


????private?static?final?Logger LOGGER = LoggerFactory.getLogger(DataSourceContextHolder.class);


????private?static?final?ThreadLocal contextHolder =?new?ThreadLocal<>();?//實(shí)際上就是開(kāi)啟多個(gè)線程光坝,每個(gè)線程進(jìn)行初始化一個(gè)數(shù)據(jù)源

????/**

?????* 設(shè)置數(shù)據(jù)源

?????* @param dbTypeEnum

?????*/

????public?static?void?setDbType(DBTypeEnum dbTypeEnum) {

????????contextHolder.set(dbTypeEnum.getValue());

????}


????/**

?????* 取得當(dāng)前數(shù)據(jù)源

?????* @return

?????*/

????public?static?String getDbType() {

????????return?(String) contextHolder.get();

????}


????/**

?????* 清除上下文數(shù)據(jù)

?????*/

????public?static?void?clearDbType() {

????????contextHolder.remove();

????}

}

6、AOP實(shí)現(xiàn)的數(shù)據(jù)源切換

@Order設(shè)置的足夠小是為了讓他先執(zhí)行

/**

?* aop的實(shí)現(xiàn)的數(shù)據(jù)源切換<br> * aop切點(diǎn)甥材,實(shí)現(xiàn)mapper類找尋,找到所屬大本營(yíng)以后性含,如db1Aspect(),則會(huì)調(diào)用<br> * db1()前面之前的操作洲赵,進(jìn)行數(shù)據(jù)源的切換。

?*/

@Component

@Order(value = -100)

@Slf4j

@Aspect

public?class?DataSourceAspect {


????@Pointcut("execution(* com.zwyl.bazhong.dao.mapper.db1..*.*(..))")

????private?void?db1Aspect() {

????}


????@Pointcut("execution(* com.zwyl.bazhong.dao.mapper.db2..*.*(..))")

????private?void?db2Aspect() {

????}


????@Before("db1Aspect()")

????public?void?db1() {

????????log.info("切換到db1 數(shù)據(jù)源...");

????????DataSourceContextHolder.setDbType(DBTypeEnum.db1);

????}


????@Before("db2Aspect()")

????public?void?db2() {

????????log.info("切換到db2 數(shù)據(jù)源...");

????????DataSourceContextHolder.setDbType(DBTypeEnum.db2);

????}

}

7、mapper層結(jié)構(gòu)


8叠萍、寫一個(gè)service測(cè)試一下

@Service

public?class?DictServiceImpl?implements?IDictService {


????@Resource

????private?PtDictMapper ptDictMapper;?//來(lái)自db1


????@Resource

????private?SysDictMapper sysDictMapper;?// 來(lái)自db2



????@Override

????public?void?getById(String id) {

????????PtDict dict = ptDictMapper.selectById("2bf6257fc8fe483c84c1ad7e89d632f6");

????????SysDict sysDict = sysDictMapper.getById("49");

????????System.out.println("123");

????}

}

9芝发、測(cè)試結(jié)果


總結(jié): 其實(shí)整個(gè)過(guò)程可以理解成,配置多數(shù)據(jù)源 xml中 ?-------> 然后通過(guò)加載多數(shù)源到spring工廠中-------->然后創(chuàng)建多線程苛谷,每個(gè)數(shù)據(jù)源對(duì)應(yīng)一個(gè)數(shù)據(jù)源--------->然后實(shí)際調(diào)用時(shí)候辅鲸,會(huì)先通過(guò)aop匹配到某一具體數(shù)據(jù)源------------->然后實(shí)例化當(dāng)前數(shù)據(jù)源

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腹殿,隨后出現(xiàn)的幾起案子独悴,更是在濱河造成了極大的恐慌,老刑警劉巖锣尉,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刻炒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡自沧,警方通過(guò)查閱死者的電腦和手機(jī)坟奥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拇厢,“玉大人爱谁,你說(shuō)我怎么就攤上這事⌒①耍” “怎么了访敌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)邪媳。 經(jīng)常有香客問(wèn)我捐顷,道長(zhǎng),這世上最難降的妖魔是什么雨效? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任迅涮,我火速辦了婚禮,結(jié)果婚禮上徽龟,老公的妹妹穿的比我還像新娘叮姑。我一直安慰自己,他們只是感情好据悔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布传透。 她就那樣靜靜地躺著,像睡著了一般极颓。 火紅的嫁衣襯著肌膚如雪朱盐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天菠隆,我揣著相機(jī)與錄音兵琳,去河邊找鬼狂秘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛躯肌,可吹牛的內(nèi)容都是我干的者春。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼清女,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼钱烟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起嫡丙,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拴袭,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后迄沫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體稻扬,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年羊瘩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泰佳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尘吗,死狀恐怖逝她,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情睬捶,我是刑警寧澤黔宛,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站擒贸,受9級(jí)特大地震影響臀晃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜介劫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一徽惋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧座韵,春花似錦险绘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至黔帕,卻和暖如春代咸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背成黄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工侣背, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留白华,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓贩耐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親厦取。 傳聞我的和親對(duì)象是個(gè)殘疾皇子潮太,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354