1.数据库连接信息配置
#master数据库
spring.datasource.druid.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.master.jdbc-url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.druid.master.username=root
spring.datasource.druid.master.password=root
#slave数据库
spring.datasource.druid.slave.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.druid.slave.jdbc-url=jdbc:oracle:thin:@127.0.0.1:1521/orcl
spring.datasource.druid.slave.username=wbs
spring.datasource.druid.slave.password=wbs
2.动态数据源配置
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
@Configuration
@MapperScan(basePackages = "com.**.dao.mapper")
public class DataSourceConfig {
@Bean(DataSourceConstants.DS_KEY_MASTER)
@ConfigurationProperties(prefix = "spring.datasource.druid.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(DataSourceConstants.DS_KEY_SLAVE)
@ConfigurationProperties(prefix = "spring.datasource.druid.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public DataSource dynamicDataSource() {
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put(DataSourceConstants.DS_KEY_MASTER, masterDataSource());
dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE, slaveDataSource());
//设置动态数据源
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
return dynamicDataSource;
}
}
/**
* 动态数据源
*
* @author: haojl
* @since: 2022/3/23
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getContextKey();
}
}
3.动态选择数据源
/**
* 动态数据源名称上下文处理
**/
public class DynamicDataSourceContextHolder {
/**
* 动态数据源名称上下文
*/
private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>();
/**
* 设置数据源
* @param key
*/
public static void setContextKey(String key){
System.out.println("切换数据源"+key);
DATASOURCE_CONTEXT_KEY_HOLDER.set(key);
}
/**
* 获取数据源名称
* @return
*/
public static String getContextKey(){
String key = DATASOURCE_CONTEXT_KEY_HOLDER.get();
return key == null?DataSourceConstants.DS_KEY_MASTER:key;
}
/**
* 删除当前数据源名称
*/
public static void removeContextKey(){
DATASOURCE_CONTEXT_KEY_HOLDER.remove();
}
}
/**
* 数据源常量
**/
public class DataSourceConstants {
/**
* master数据源
*/
public static final String DS_KEY_MASTER = "master";
/**
* slave数据源
*/
public static final String DS_KEY_SLAVE = "slave";
}
4.使用 AOP 选择数据源
定义数据源注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DS {
String value() default DataSourceConstants.DS_KEY_MASTER;
}
定义数据源切面
@Aspect
@Component
@Order(-100)
public class DynamicDataSourceAspect {
private static final Logger loger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
@Pointcut("@annotation(com.lhzw.platform.core.common.aop.annotation.DS)")
public void dataSourcePointCut(){
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
String dsKey = getDSAnnotation(joinPoint).value();
DynamicDataSourceContextHolder.setContextKey(dsKey);
try{
return joinPoint.proceed();
}finally {
DynamicDataSourceContextHolder.removeContextKey();
}
}
/**
* 根据类或方法获取数据源注解
* @param joinPoint
* @return
*/
private DS getDSAnnotation(ProceedingJoinPoint joinPoint){
Class<?> targetClass = joinPoint.getTarget().getClass();
DS dsAnnotation = targetClass.getAnnotation(DS.class);
// 先判断类的注解,再判断方法注解
if(Objects.nonNull(dsAnnotation)){
return dsAnnotation;
}else{
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(DS.class);
}
}
}
5.使用自定义注解进行数据源切换
@DS(DataSourceConstants.DS_KEY_SLAVE)
@Override
public List<Map<String, Object>> list() {
return testOrclMapper.list();
}
@Override
public List<Map<String, Object>> list1() {
return testOrclMapper.list1();
}