有个需求需要通过开关控制需要访问的数据源,此处参考DS多数据源,采用注解加aop切面实现此功能。
配置文件开关:
XML
slave-config:
mainSlaveSwitch: true
配置开关类:
java
@Component
@RefreshScope
@Data
@ConfigurationProperties("slave-config")
public class SlaveConfig {
private boolean mainSlaveSwitch=false;
}
多数据源配置:
XML
datasource:
dynamic:
primary: master
datasource:
master:
url: jdbc:mysql://xxxx:3306/order?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: gac_travel_dev
password: gac@6666
driverClassName: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initialSize: 10
maxActive: 20
minIdle: 5
maxWait: 1000
minEvictableIdleTimeMillis: 300000
useGlobalDataSourceStat: true
timeBetweenEvictionRunsMillis: 60000
validationQuery: select 'x'
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
slave:
url: jdbc:mysql://xxxx:3306/order/gac_order?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: gac_dev_read
password: gac@6666
type: com.alibaba.druid.pool.DruidDataSource
druid:
initialSize: 10
maxActive: 20
minIdle: 5
maxWait: 1000
minEvictableIdleTimeMillis: 300000
useGlobalDataSourceStat: true
timeBetweenEvictionRunsMillis: 60000
validationQuery: select 'x'
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
mainslave:
url: jdbc:mysql://xxxx:3306/order/gac_order?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: gac_travel_test
password: gac@6666
type: com.alibaba.druid.pool.DruidDataSource
druid:
initialSize: 10
maxActive: 20
minIdle: 5
maxWait: 1000
minEvictableIdleTimeMillis: 300000
useGlobalDataSourceStat: true
timeBetweenEvictionRunsMillis: 60000
validationQuery: select 'x'
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
多数据源静态类(不是必须的):
XML
public interface DBTypeConst {
/**
* 主库
*/
String MASTER = "master";
/**
* 主库的从库
*/
String MAIN_SLAVE = "mainslave";
/**
* 从库
*/
String SLAVE = "slave";
}
多数据源注解:
java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicDataSource {
}
AOP切面:
java
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
@Aspect
@Component
@Slf4j
public class DynamicDataSourceAspect {
@Autowired
SlaveConfig slaveConfig;
@Around("@annotation(dynamicDataSource)")
public Object switchDataSource(ProceedingJoinPoint joinPoint, DynamicDataSource dynamicDataSource) throws Throwable {
if(slaveConfig.isMainSlaveSwitch()){
log.info("DynamicDataSourceAspect:{}",DBTypeConst.MAIN_SLAVE);
DynamicDataSourceContextHolder.push(DBTypeConst.MAIN_SLAVE);
}else{
log.info("DynamicDataSourceAspect:{}",DBTypeConst.SLAVE);
DynamicDataSourceContextHolder.push(DBTypeConst.SLAVE);
}
try {
return joinPoint.proceed();
} finally {
DynamicDataSourceContextHolder.clear();
}
}
}
此处使用时要多测试防止异常