Druid數(shù)據(jù)庫多數(shù)據(jù)源
Spring的多數(shù)據(jù)源支持—AbstractRoutingDataSource,AbstractRoutingDataSource定義了抽象的determineCurrentLookupKey方法,子類實現(xiàn)此方法,來確定要使用的數(shù)據(jù)源
Druid 實現(xiàn)多數(shù)據(jù)源支持,核心是Overwrite AbstractRoutingDataSource 的 determineCurrentLookupKey 方法
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
// 確定當(dāng)前要使用的數(shù)據(jù)源
protected abstract Object determineCurrentLookupKey();
}
配置多數(shù)據(jù)源
以springboot框架為基礎(chǔ)使用aop注解的方式依賴Druid配置多數(shù)據(jù)源
1.添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- aop注解實現(xiàn)aspectjweaver依賴 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
2.配置Druid屬性
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
first:
url: jdbc:mysql://localhost:3306/***?useUnicode=true&characterEncoding=utf- 8&serverTimezone=UTC
username: root
password: *****
second:
enable: true
url: jdbc:mysql://localhost:3306/***?useUnicode=true&characterEncoding=utf- 8&serverTimezone=UTC
username: root
password: *****
druid:
# 初始連接數(shù)
initialSize: 5
# 最小連接池數(shù)量
minIdle: 10
# 最大連接池數(shù)量
maxActive: 20
# 配置獲取連接等待超時的時間
maxWait: 60000
# 配置間隔多久才進(jìn)行一次檢測,檢測需要關(guān)閉的空閑連接,單位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一個連接在池中最小生存的時間,單位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一個連接在池中最大生存的時間,單位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置檢測連接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 控制臺管理用戶名和密碼
login-username: admin
login-password: 123456
#配置監(jiān)控統(tǒng)計攔截的filters:stat:監(jiān)控統(tǒng)計、self4j(使用log4j的記得導(dǎo)入log4j的依賴):日志記錄、 wall:防御sql注入 此處配置不能遺漏服務(wù)sql監(jiān)控臺不能監(jiān)控sql
filters: stat,wall,log4j2
filter:
stat:
enabled: true
# 慢SQL記錄
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
enabled: true
config:
multi-statement-allow: true
3.配置動態(tài)數(shù)據(jù)源
繼承AbstractRoutingDataSource重寫determineCurrentLookupKey()方法
/**
* 動態(tài)數(shù)據(jù)源
*/
public class DynamicDatesource extends AbstractRoutingDataSource {
public DynamicDatesource(DataSource dataSource,HashMap<Object, Object> map){
super.setDefaultTargetDataSource(dataSource);
super.setTargetDataSources(map);
super.afterPropertiesSet();
}
/**
* 獲取key指定數(shù)據(jù)源
* @return
*/
@Override
protected Object determineCurrentLookupKey() {
return DynamicDateSourceCut.getLocal();
}
}
配置數(shù)據(jù)源文章來源:http://www.zghlxwxcb.cn/news/detail-515391.html
//配置數(shù)據(jù)源
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.first")
public DataSource firstDataSource(DruidSourceProperties druidSourceProperties){
return druidSourceProperties.dataSource(new DruidDataSourceWrapper());
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.second")
@ConditionalOnProperty(prefix ="spring.datasource.second",name ="enable",havingValue = "true")
public DataSource secondDataSource(DruidSourceProperties druidSourceProperties){
return druidSourceProperties.dataSource(new DruidDataSourceWrapper());
}
@Bean
@Primary//在多數(shù)據(jù)源的時候,使用@Primary注解用于指定其中一個作為主數(shù)據(jù)源
public DynamicDatesource setDymaicDatesource(DataSource firstDataSource){
HashMap<Object, Object> map = new HashMap<>();
map.put(DateSourceType.FIRST.name(),firstDataSource);
setDataSource(map,DateSourceType.SECOND.name(),"secondDataSource");
return new DynamicDatesource(firstDataSource,map);
}
/**
* 設(shè)置數(shù)據(jù)源
*
* @param targetDataSources 備選數(shù)據(jù)源集合
* @param sourceName 數(shù)據(jù)源名稱
* @param beanName bean名稱
*/
public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName){
try {
DataSource dataSource = SpringUtils.getBean(beanName);
targetDataSources.put(sourceName, dataSource);
} catch (Exception e){
}
}
}
4.配置數(shù)據(jù)源切換
package com.example.springboot.data;
/**
*數(shù)據(jù)源切換 保存每個數(shù)據(jù)源指定的lookupKey
*/
public class DynamicDateSourceCut {
/**
* 使用ThreadLocal維護(hù)變量,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,
* 所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應(yīng)的副本。
*/
private static ThreadLocal<String> threadLocal=new ThreadLocal<>();
/**
* 設(shè)置數(shù)據(jù)源的變量
*/
public static void setLocal(String local){
threadLocal.set(local);
}
/**
* 獲得數(shù)據(jù)源的變量
*/
public static String getLocal(){
return threadLocal.get();
}
/**
* 清空數(shù)據(jù)源變量
*/
public static void clearLocl() {
threadLocal.remove();
}
}
5.定義aop切面實現(xiàn)
/**
* 定義數(shù)據(jù)源切面
*/
@Aspect
@Component
public class DateSourceAspect {
private static final Logger log= LoggerFactory.getLogger(DateSourceAspect.class);
/**
* 定義切點 使用注解
* @within類注解
* @annotation方法注解
*/
@Pointcut("@annotation(com.example.springboot.aspect.DateSource)"+
"||@within(com.example.springboot.aspect.DateSource)")
public void PintCut(){
}
/**
* 通知使用環(huán)繞的通知方法
*/
@Around("PintCut()")
public Object ResovePoint(ProceedingJoinPoint point) throws Throwable {
//獲取注解
DateSource dateSource = getDateSource(point);
if (dateSource!=null){
DynamicDateSourceCut.setLocal(dateSource.value().name());
}
try {
//執(zhí)行方法
return point.proceed();
} finally {
// 銷毀數(shù)據(jù)源 在執(zhí)行方法之后
DynamicDateSourceCut.clearLocl();
}
}
/**
* 獲取注解
*/
protected DateSource getDateSource(ProceedingJoinPoint point){
MethodSignature signature = (MethodSignature) point.getSignature();
//獲取方法或方法類型上的注解
DateSource annotation;
//獲取class類型上注解
annotation=AnnotationUtils.findAnnotation(signature.getDeclaringType(),DateSource.class);
if (annotation==null){
annotation = AnnotationUtils.findAnnotation(signature.getMethod(), DateSource.class);
}
return annotation;
}
}
定義的注解和注解值文章來源地址http://www.zghlxwxcb.cn/news/detail-515391.html
/**
* 定義注解
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DateSource {
DateSourceType value()default DateSourceType.FIRST;
}
/**
*使用枚舉定義注解的值
*/
public enum DateSourceType {
//默認(rèn)數(shù)據(jù)庫
FIRST,
SECOND;
}
到了這里,關(guān)于Springboot+Druid配置多數(shù)據(jù)源的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!