文章目录
一、创建数据源
在application.properties文件中配置多个数据源的连接信息,例如:
这里以properties配置文件为例,yaml配置文件同理配置即可
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.mysql.jdbc.Driver
# 主数据源
spring.datasource.druid.master.url=jdbcUrl
spring.datasource.druid.master.username=***
spring.datasource.druid.master.password=***
# 其他数据源
spring.datasource.druid.second.url=jdbcUrl
spring.datasource.druid.second.username=***
spring.datasource.druid.second.password=***
二、创建多个数据源配置类
为数据源创建一个配置类,分别配置数据源的连接信息和相关的Bean。例如:
@Configuration
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid.master")
public DataSource firstDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.second")
public DataSource secondDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>(5);
targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
return new DynamicDataSource(firstDataSource, targetDataSources);
}
}
注意:该配置类必须在启动类同级目录下,或同级子目录下,否则项目启动时,无法将bean添加到Spring容器中!
三、自定义注解用于标记哪些方法需要动态切换数据源
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceSwitch {
String value() default "defaultDataSource";
}
四、创建一个数据源切换类,用于在运行时动态切换数据源
public class DataSourceContextHolder {
// 数据源容器
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
// 设置数据源
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
// 获取数据源
public static String getDataSource() {
return contextHolder.get();
}
// 移除数据源
public static void clearDataSource() {
contextHolder.remove();
}
}
五、创建数据源切换切面
使用AOP切面,在每个需要切换数据源的方法上进行切面处理
@Aspect
@Component
public class DataSourceSwitchAspect {
// 这里的注解路径根据你自己的路径填写
@Before("@annotation(com.example.demo.annotation.DataSourceSwitch)")
public void switchDataSource(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
DataSourceSwitch dataSourceSwitch = method.getAnnotation(DataSourceSwitch.class);
String dataSource = dataSourceSwitch.value();
DataSourceContextHolder.setDataSource(dataSource);
}
// 这里的注解路径根据你自己的路径填写
@After("@annotation(com.example.demo.annotation.DataSourceSwitch)")
public void restoreDataSource(JoinPoint joinPoint) {
DataSourceContextHolder.clearDataSource();
}
}
DataSourceAspect拦截业务方法,更新当前线程上下文DataSourceContextHolder中存储的key,即可实现数据源切换
六、在需要切换数据源的方法上添加注解
@DataSourceSwitch("second")
public void doSomething() {
// 执行自己的业务逻辑
}