springboot动态切换数据源
第一步加入POM
除去自己本身项目需要用得POM之外,还需要添加以下Druid连接依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
第二步配置spring
import lombok.Getter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* <code>SpringUtil</code> spring工具类。
*
* @author PengXiuYuan
* @date 2020-08-20
* @since 1.0.0
*/
@Component
public class SpringUtil implements ApplicationContextAware {
@Getter
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
public static <T> T getBean(Class<T> clazz) {
return SpringUtil.applicationContext.getBean(clazz);
}
public static Object getBean(String name) {
return SpringUtil.applicationContext.getBean(name);
}
public static String getProperty(String key) {
return SpringUtil.applicationContext.getEnvironment().getProperty(key);
}
}
第三步配置数据源
import com.alibaba.druid.pool.DruidDataSource;
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.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
/**
* <code>DataSourceConfig</code> 数据源配置。
*
* @author PengXiuYuan
* @date 2020-08-20
* @since 1.0.0
*/
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid")
public DataSource defaultDataSource() {
DruidDataSource build = DruidDataSourceBuilder.create().build();
return build;
}
@Bean
@Primary
@DependsOn({"springUtil", "defaultDataSource"})
public DynamicDataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(DynamicDataSource.dataSourcesMap);
return dynamicDataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
第四步配置动态数据源
import com.dreawer.tdc.utils.SpringUtil;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* <code>DynamicDataSource</code> 动态数据源。
*
* @author PengXiuYuan
* @date 2020-08-20
* @since 1.0.0
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> dataSourceKey = ThreadLocal.withInitial(() -> "defaultDataSource");
public static Map<Object, Object> dataSourcesMap = new ConcurrentHashMap<>(20);
static {
dataSourcesMap.put("defaultDataSource", SpringUtil.getBean("defaultDataSource"));
}
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSource.dataSourceKey.get();
}
public static void setDataSource(String dataSource) {
DynamicDataSource.dataSourceKey.set(dataSource);
DynamicDataSource dynamicDataSource = (DynamicDataSource) SpringUtil.getBean("dataSource");
dynamicDataSource.afterPropertiesSet();
}
public static String getDataSource() {
return DynamicDataSource.dataSourceKey.get();
}
public static void clear() {
DynamicDataSource.dataSourceKey.remove();
}
第五步配置默认数据源
# DATASOURCE
spring.datasource.druid.default-auto-commit = true
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=
spring.datasource.password=
spring.datasource.url=
第六步实际运用
1.添加数据源
我做的就是连接不同环境的数据库,如果知道要连接哪些数据库可以先多次调用该方法先添加到数据源里面。
/**
* 设置数据源。
* @param env 环境。
* @param databaseName 数据源名称。
* @author PengXiuYuan
* @date 2020-08-20
* @since 1.0.0
*/
public void setDataSource(DataSourceEnvironment env, String databaseName) {
DruidDataSource druidDataSource = new DruidDataSource();
switch (env) {
case DEV:
if (StringUtils.isEmpty(databaseName)) {
databaseName = "testinfo_dev";
}
druidDataSource.setUrl(String.format(devDataSourceUrl, databaseName));
druidDataSource.setUsername(devUserName);
druidDataSource.setPassword(devPassword);
break;
case TEST3:
if (StringUtils.isEmpty(databaseName)) {
databaseName = "cc-test3";
}
druidDataSource.setUrl(String.format(testDataSourceUrl, databaseName));
druidDataSource.setUsername(testUserName);
druidDataSource.setPassword(testPassword);
break;
case UAT:
if (StringUtils.isEmpty(databaseName)) {
databaseName = "cc-uat";
}
druidDataSource.setUrl(String.format(uatDataSourceUrl, databaseName));
druidDataSource.setUsername(uatUserName);
druidDataSource.setPassword(uatPassword);
break;
}
DynamicDataSource.dataSourcesMap.put(databaseName, druidDataSource);
DynamicDataSource.setDataSource(databaseName);
}
2.例子
/**
* 例子。
* @author PengXiuYuan
* @date 2020-08-20
* @since 1.0.0
*/
public void test() {
//切换数据源,在此之前就已经添加到数据源里面
DynamicDataSource.setDataSource(databaseName);
//业务代码
//关闭数据源
DynamicDataSource.setDataSource(dataSource);
}
自此就完成了多数据源添加与切换功能了,欢迎大家评论与交流!