多数据源, 不考虑主从, 分库分表的情况下
采用自定义注解+AOP+AbstractRoutingDataSource实现
- 初始化时, 实例化需要的数据源, 并塞到map中(yml配置好数据源即可)
@Bean
@ConfigurationProperties("spring.datasource.druid.first")
public DataSource firstDataSource() {
LOGGER.info("first 数据源初始化成功!!!");
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.second")
public DataSource secondDataSource() {
LOGGER.info("second 数据源初始化成功!!!");
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {
// 用于动态切换数据源
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.FIRST, firstDataSource);
targetDataSources.put(DataSourceType.SECOND, secondDataSource);
return new DynamicDataSource(firstDataSource, targetDataSources);
}
- 主要切面方法如下, 根据注解的type()动态切换数据源
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource ds = method.getAnnotation(DataSource.class);
if (ds == null) { // 默认采用First这个数据源
DynamicDataSource.setDataSource(DataSourceType.FIRST);
} else {
DynamicDataSource.setDataSource(ds.type());
}
LOGGER.info("当前接口使用的数据源是 " + DynamicDataSource.getDataSource());
try {
return point.proceed();
} finally { // ThreadLocal remove
DynamicDataSource.clearDataSource();
}
}
- 使用方式: 直接使用注解即可
@Override
@DataSource(type = DataSourceType.FIRST)
public List<Demo> getFirst() {
return list();
}
@Override
@DataSource(type = DataSourceType.SECOND)
public List<Demo> getSecond() {
return list();
}
考虑主从的情况下, 每套主从数据源, 都持有自己mapper逻辑
- 最重要的是配置yml
sharding:
jdbc:
datasource: # 好像pg和mysql不兼容???
names: my-master,my-slave,pg-master,pg-slave # 不能含有空格
my-master: mysql主库配置
my-slave: mysql从库配置
pg-master: pg主库配置
pg-slave: pg从库配置
config:
props:
sql:
show: true
sharding:
master-slave-rules:
first:
masterDataSourceName: my-master
slaveDataSourceNames:
- my-slave
loadBalanceAlgorithmType: ROUND_ROBIN
second:
masterDataSourceName: pg-master
slaveDataSourceNames:
- pg-slave
loadBalanceAlgorithmType: ROUND_ROBIN
default-data-source-name: first
default-database-strategy:
hint:
algorithm-class-name: cn.az.project.alg.MyDataSourceRoutingAlgorithm
- 实现routing算法 HintShardingAlgorithm
@Override
@SuppressWarnings("unchecked")
public Collection<String> doSharding(Collection<String> availableTargetNames, ShardingValue shardingValue) {
LOGGER.info("shardingValue=" + shardingValue);
LOGGER.info("availableTargetNames=" + availableTargetNames);
List<String> shardingResult = new ArrayList<>();
ListShardingValue<String> tmpSharding = (ListShardingValue<String>) shardingValue;
for (String value : tmpSharding.getValues()) {
if (availableTargetNames.contains(value)) {
shardingResult.add(value);
}
}
return shardingResult;
}
- 实现切面, 针对每个主从数据源
@Pointcut("execution(* cn.az.project.mapper.first..*.*(..))")
public void switchFirst() {
}
@Before("switchFirst()")
public void switchFirstBefore() {
HintManager hintManager = HintManager.getInstance();
hintManager.setDatabaseShardingValue(DataSourceType.FIRST);
logger.info("切换到MYSQL数据源~");
}
/**
* 恢复默认数据源
*/
@After("switchFirst()")
public void switchFirstAfter() {
//清理掉当前设置的数据源,让默认的数据源不受影响
HintManager hintManager = HintManagerHolder.get();
if (hintManager != null) {
hintManager.close();
}
}
项目地址, 参考这里
主要用于个人纪录学习内容, 还请多多关照