一:Mybatis通过自定义注解方式实现
1.添加阿里巴巴druid数据库连接池依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
2.修改配置文件
我这里分别用的是阿里云与华为云
spring:
datasource:
druid:
alibaba:
driver-class-name: com.mysql.cj.jdbc.Driver
username: userName
password: password
url: jdbc:mysql://host:port/database?useUnicode=true&characterEncoding=utf8&createDatabaseIfNotExist=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
huawei:
driver-class-name: com.mysql.cj.jdbc.Driver
username: username
password: password
url: jdbc:mysql://host:port/database?useUnicode=true&characterEncoding=utf8&createDatabaseIfNotExist=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
3.继承AbstractRoutingDataSource类并实现determineCurrentLookupKey方法
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
// 线程隔离
private static final ThreadLocal<String> dataSourceHolder = new InheritableThreadLocal<>();
/**
* 设置数据源
*/
public static void setDataSource(String dataSource) {
dataSourceHolder.set(dataSource);
}
/**
* 清除数据源
*/
public static void removeDataSource() {
dataSourceHolder.remove();
}
/**
* 获取当前数据源
*/
@Override
protected Object determineCurrentLookupKey() {
return dataSourceHolder.get();
}
}
4.创建自定义注解,通过此注解指定数据源
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 切换指定数据源注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomDataSource {
String value() default "alibaba";
}
5.新建AOP切面,切上面新建的自定义注解
import com.xxx.xxx.annotation.CustomDataSource;
import com.xxx.xxx.config.DynamicDataSource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAspect {
@Around("@annotation(com.xxx.xxx.annotation.CustomDataSource) || @within(com.xxx.xxx.annotation.CustomDataSource)")
public Object switchDataSource(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
CustomDataSource dataSource = signature.getMethod().getAnnotation(CustomDataSource.class);
if (dataSource == null) {
Class<?> declaringType = signature.getDeclaringType();
dataSource = declaringType.getAnnotation(CustomDataSource.class);
}
if (dataSource == null) {
// 这里我默认了使用阿里巴巴
DynamicDataSource.setDataSource("alibaba");
} else {
DynamicDataSource.setDataSource(dataSource.value());
}
try {
return point.proceed();
} finally {
DynamicDataSource.removeDataSource();
}
}
}
6.新建多数据源配置类
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
/**
* 配置多数据源
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.alibaba")
public DataSource alibabaDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.huawei")
public DataSource huaweiDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 配置动态数据源
*/
@Bean
public DynamicDataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("alibaba", alibabaDataSource());
targetDataSources.put("huawei", huaweiDataSource());
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(alibabaDataSource());
return dataSource;
}
}
7.新建mybatis配置类
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
/**
* 配置多数据源
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.alibaba")
public DataSource alibabaDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.huawei")
public DataSource huaweiDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 配置动态数据源
*/
@Bean
public DynamicDataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("alibaba", alibabaDataSource());
targetDataSources.put("huawei", huaweiDataSource());
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(alibabaDataSource());
return dataSource;
}
}
8.需要指定数据源的方法上增加注解
@CustomDataSource("huawei")
@Override
public User getUserFromHuawei(Long id) {
return userMapper.selectById(id);
}
二:mybatis-plus实现方式
1.添加多数据源maven依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
</dependency>
2.修改配置文件
spring:
datasource:
dynamic:
primary: alibaba # 默认数据源
strict: false
datasource:
alibaba:
driver-class-name: com.mysql.cj.jdbc.Driver
username: userName
password: password
url: jdbc:mysql://host:port/database?useUnicode=true&characterEncoding=utf8&createDatabaseIfNotExist=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
huawei:
driver-class-name: com.mysql.cj.jdbc.Driver
username: username
password: password
url: jdbc:mysql://host:port/database?useUnicode=true&characterEncoding=utf8&createDatabaseIfNotExist=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
3.需要指定数据源的方法上增加注解
@DS("huawei")
@Override
public User getUserFromHuawei(Long id) {
return userMapper.selectById(id);
}
三:测试
image.png
image.png