一:Mybatis通過(guò)自定義注解方式實(shí)現(xiàn)
1.添加阿里巴巴druid數(shù)據(jù)庫(kù)連接池依賴
<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類并實(shí)現(xiàn)determineCurrentLookupKey方法
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
// 線程隔離
private static final ThreadLocal<String> dataSourceHolder = new InheritableThreadLocal<>();
/**
* 設(shè)置數(shù)據(jù)源
*/
public static void setDataSource(String dataSource) {
dataSourceHolder.set(dataSource);
}
/**
* 清除數(shù)據(jù)源
*/
public static void removeDataSource() {
dataSourceHolder.remove();
}
/**
* 獲取當(dāng)前數(shù)據(jù)源
*/
@Override
protected Object determineCurrentLookupKey() {
return dataSourceHolder.get();
}
}
4.創(chuàng)建自定義注解袍榆,通過(guò)此注解指定數(shù)據(jù)源
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 切換指定數(shù)據(jù)源注解
*/
@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) {
// 這里我默認(rèn)了使用阿里巴巴
DynamicDataSource.setDataSource("alibaba");
} else {
DynamicDataSource.setDataSource(dataSource.value());
}
try {
return point.proceed();
} finally {
DynamicDataSource.removeDataSource();
}
}
}
6.新建多數(shù)據(jù)源配置類
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 {
/**
* 配置多數(shù)據(jù)源
*/
@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();
}
/**
* 配置動(dòng)態(tài)數(shù)據(jù)源
*/
@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 {
/**
* 配置多數(shù)據(jù)源
*/
@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();
}
/**
* 配置動(dòng)態(tài)數(shù)據(jù)源
*/
@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.需要指定數(shù)據(jù)源的方法上增加注解
@CustomDataSource("huawei")
@Override
public User getUserFromHuawei(Long id) {
return userMapper.selectById(id);
}
二:mybatis-plus實(shí)現(xiàn)方式
1.添加多數(shù)據(jù)源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 # 默認(rèn)數(shù)據(jù)源
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.需要指定數(shù)據(jù)源的方法上增加注解
@DS("huawei")
@Override
public User getUserFromHuawei(Long id) {
return userMapper.selectById(id);
}