首先Springboot+Mybatis+druid动态多数据源的配置是这样的
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan(basePackages = "com.xxx.xxx.mapper")
@Import({DynamicDataSourceConfig.class})
public class BootApplication {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
SpringApplication.run(BootApplication.class, args);
}
}
application.pro的关键配置如下:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 配置监控服务器:http://ip:端口/druid/index.html
stat-view-servlet:
login-username: admin
login-password: kisen@123
reset-enable: false
url-pattern: /druid/*
master: # 主数据源
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://167.1.6.163:53306/master?serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
slave: # 从数据源
# driverClassName: org.postgresql.Driver
# username: postgres
# password: postgres
# url: jdbc:postgresql://192.168.30.22:5432/slave_db
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://157.1.6.134:53
动态切换的配置文件如下:
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "";
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("@annotation(DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if(dataSource == null){
DynamicDataSource.setDataSource("master");
}else {
System.out.println("dataSource.name()===="+dataSource.name());
DynamicDataSource.setDataSource(dataSource.name());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
private static Logger log = LoggerFactory.getLogger(DynamicDataSource.class);
@Override
protected Object determineCurrentLookupKey() {
// log.info("getDataSource()===================="+getDataSource());
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
log.info("切换到{"+dataSource+"}数据源");
log.info("切换到{"+dataSource+"}数据源");
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
下面是最关键的地方,要对普通的druid多数据源动态切换做如下修改
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 org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DynamicDataSourceConfig {
@Bean(name = "master")
@ConfigurationProperties("spring.datasource.druid.master")
public DataSource masterDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "slave")
@ConfigurationProperties("spring.datasource.druid.slave")
public DataSource anjianSlaveDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "sharding")
public DataSource getShardingDataSource() throws SQLException {
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
// 分库分表逻辑,在这里不做代码展示
return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig,new ConcurrentHashMap(), properties);
}
public Map<String, DataSource> createDataSourceMap() {
Map<String, DataSource> dataSourceMap = new HashMap<String, DataSource>(4);
// 配置第一个数据源
DruidDataSource data1 = new DruidDataSource();
data1.setDriverClassName("数据源驱动");
data1.setUrl("数据库链接1");
data1.setUsername("用户名");
data1.setPassword("密码");
dataSourceMap.put("data1 ", data1 );
// 配置第二个数据源
DruidDataSource data2 = new DruidDataSource();
data2.setDriverClassName("数据源驱动");
data2.setUrl("数据库链接2");
data2.setUsername("用户名");
data2.setPassword("密码");
dataSourceMap.put("data2 ", data2 );
// 配置第三个数据源
DruidDataSource data3 = new DruidDataSource();
data3.setDriverClassName("数据源驱动");
data3.setUrl("数据库链接3");
data3.setUsername("用户名");
data3.setPassword("密码");
dataSourceMap.put("data3", data3);
// 配置第四个数据源
DruidDataSource data4 = new DruidDataSource();
data4.setDriverClassName("数据源驱动");
data4.setUrl("j数据库链接4");
data4.setUsername("用户名");
data4.setPassword("密码");
dataSourceMap.put("data4", data4);
return dataSourceMap;
}
}
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
// 配置多数据源
Map<Object, Object> dsMap = new HashMap();
dsMap.put("master", masterDataSource());
dsMap.put("slave-anjian", anjianSlaveDataSource());
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
/**
* 配置@Transactional注解事物
* @return
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
}
}