需求:對不同的數據庫進行操作,如讀寫分離
思想:在對數據庫進行操作時,程序會默認去找數據源,從數據源獲取一個連接connection,要做的點是在程序調用之前把數據源換了(例如本身默認是寫,換成讀的數據源),spring boot提供了一個AbstractRoutingDataSource類,翻譯過來是抽象路由數據源,這個類可以指定使用的數據源,繼承這個抽象類之后需要實現兩個方法,一個方法是用來添加數據源的(讀寫分離就兩個數據源,有其他的也可以添加進去),設置默認數據源的,還有一個是指定使用的數據源的。方法添加數據源的時候是以鍵值對的形式添加到map中,當指定數據源的方法返回的值在map中存在時,就是用這個key對應的數據源,如果不存在,就會使用設置的默認數據源
這里使用aop的方式來進行數據源的動態切換,先看數據源配置(這里兩個數據源是讀寫分離,寫在本機上,讀在虛擬機上)
application.xml:
server:
port: 9222
spring:
datasource:
localmysql:
username: root
password: root
url: jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=utf8
driverClassName: com.mysql.cj.jdbc.Driver
remomysql:
username: root
password: root
url: jdbc:mysql://172.21.4.130:3306/mytest?useUnicode=true&characterEncoding=utf8
driverClassName: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
數據源配置為bean,加入ioc,供后面切換:
DatabaseResourceConfig
package com.gzt.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @Description:
* @Author: guozhengtao
* @Date: 2022/1/29 11:48
*/
數據源key枚舉:DatabaseSelectEnum
package com.gzt.config;
/**
* @Description: 定義一個枚舉變量,當枚舉變量的值為write是,選擇寫入的數據庫連接,當枚舉變量的值為read時,返回讀取的數據庫連接
* @Author: guozhengtao
* @Date: 2022/1/29 13:30
*/
public enum DatabaseSelectEnum {
/**
* 選擇寫枚舉
* */
Write("write"),
/**
* 選擇讀枚舉
* */
Read("read");
private final String select;
DatabaseSelectEnum(String select) {
this.select = select;
}
public String getSelect() {
return select;
}
}
數據源切換適配:DatabaseAdapt
package com.gzt.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @Description:
* @Author: guozhengtao
* @Date: 2022/1/29 13:19
*/
到現在為止,數據源相關操作設置完畢,下面切換數據源的兩種方式,因為在DatabaseAdapt類中定義了一個變量flag,這個flag是數據源對應的key,有兩種方式來進行設置:
-
在方法中調用mapper之前先使用
DatabaseAdapt.flag=DatabaseSelectEnum.Write.getSelect();
-
使用aop的方式在執行方法或者類之前進行切換,主要介紹:
注解:DatabaseResourcedefine
package com.gzt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description:
* @Author: guozhengtao
* @Date: 2022/1/29 14:37
*/
Aop:DatabaseResourceToggle
package com.gzt.aspect;
import com.gzt.annotation.DatabaseResourcedefine;
import com.gzt.config.DatabaseAdapt;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* @Description:
* @Author: guozhengtao
* @Date: 2022/1/29 15:01
*/目錄結構如下:
主要代碼部分:
package com.gzt.service;
import com.gzt.annotation.DatabaseResourcedefine;
import com.gzt.entity.User;
import com.gzt.mapper.TestMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description:
* @Author: guozhengtao
* @Date: 2022/1/30 13:03
*/