配置多数据源的方式有很多,这里介绍一种我在工作中验证可行的方式。
大致的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<!-- 注意mybatis-plus的版本一定要适配springboot,否则在运行中可能会有问题 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
application.yml的数据源部分的配置如下,此处整合了druid:
spring:
datasource:
druid:
DB1:
url: jdbc:mysql://127.0.0.1:3306/db1?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull
username: root
password: root
validationQuery: select 1
maxActive: 30
minIdle: 4
initialSize: 4
testOnReturn: false
testWhileIdle: true
testOnBorrow: true
logAbandoned: false
timeBetweenEvictionRunsMillis: 600000
minEvictableIdleTimeMillis: 600000
poolPreparedStatements: true
max-open-prepared-statements: 20
removeAbandoned: true
driver-class-name: com.mysql.cj.jdbc.Driver
DB2:
url: jdbc:mysql://127.0.0.1:3306/db2?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull
username: root
password: root
validationQuery: select 1
maxActive: 30
minIdle: 4
initialSize: 4
testOnReturn: false
testWhileIdle: true
testOnBorrow: true
logAbandoned: false
timeBetweenEvictionRunsMillis: 600000
minEvictableIdleTimeMillis: 600000
poolPreparedStatements: true
max-open-prepared-statements: 20
removeAbandoned: true
driver-class-name: com.mysql.cj.jdbc.Driver
随后我们需要写一些配置类,进行配置。创建一个config包,在包内创建如下配置类:
/**
* 数据源名称
*/
public interface DataSourceName {
String DB1= "DB1";
String DB2= "DB2";
}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* DataSource 注解 标记数据源
*
* 默认数据库 Master
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value() default DataSourceName.DRDS;
}
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 配置DataSource, defaultTargetDataSource为主数据库
*/
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
* 多数据源配置
*
*/
@Configuration
public class DataSourceConfig {
private static final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
@Bean(name = "drdsDataSource")
@ConfigurationProperties("spring.datasource.druid.db1")
public DataSource reminderDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "rdsDataSource")
@ConfigurationProperties("spring.datasource.druid.db2")
public DataSource scenceDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(@Qualifier("db1DataSource") DataSource db1DataSource,
@Qualifier("db2DataSource") DataSource db2DataSource) throws SQLException {
Map<Object, Object> targetDataSources = new HashMap<>(2);
targetDataSources.put(DataSourceName.DB1, db1DataSource);
targetDataSources.put(DataSourceName.DB2, db2DataSource);
// 还有数据源,在targetDataSources中继续添加
logger.info("MultiDataSources:" + targetDataSources);
return new DynamicDataSource(db1DataSource, targetDataSources);
}
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 数据源切点配置
*
*/
@Aspect
@Component
public class DataSourceAspect implements Ordered {
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 切点: 所有配置 DataSource 注解的方法
*/
@Pointcut("@annotation(com.xx.xx.xx.config.DataSource)")
public void dataSourcePointCut() {}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource ds = method.getAnnotation(DataSource.class);
// 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
DynamicDataSource.setDataSource(ds.value());
logger.debug("set datasource is {} ", ds.value());
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
logger.debug("clean datasource");
}
}
@Override
public int getOrder() {
return 1;
}
}
经过以上操作,多数据源的配置基本完成,使用时,如果是主数据源(即:默认数据源),不需要任何进一步的操作,直接写代码即可;如果要切换到非默认数据源,只需要在接口上添加如下注解:
@DataSource(DataSourceName.DB2)
注:由于本案例使用了durid的数据源,可能在运行时会有报错,此时,在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;
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSource getDataSource() {
return new DruidDataSource();
}
}
版权声明:本文为zuodaye原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。