springboot动态切换数据源

207 阅读1分钟

1.引入druid

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.13</version>
</dependency>

2.数据源配置

spring:
  datasource:
    acct:
      username: root
      password: root
      url: jdbc:mysql://192.168.56.10:3317/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
      driver-class-name: com.mysql.cj.jdbc.Driver
    sett:
      username: root
      password: root
      url: jdbc:mysql://192.168.56.10:3307/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
      driver-class-name: com.mysql.cj.jdbc.Driver

3.DynamicDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.HashMap;
import java.util.Map;

public class DynamicDataSource extends AbstractRoutingDataSource {
	private static DynamicDataSource instance;
	private static byte[] lock=new byte[0];
	private static Map<Object,Object> dataSourceMap=new HashMap<Object, Object>();

	@Override
	public void setTargetDataSources(Map<Object, Object> targetDataSources) {
		super.setTargetDataSources(targetDataSources);
		dataSourceMap.putAll(targetDataSources);
		super.afterPropertiesSet();// 必须添加该句,否则新添加数据源无法识别到
	}

	public Map<Object, Object> getDataSourceMap() {
		return dataSourceMap;
	}

	public static synchronized DynamicDataSource getInstance(){
		if(instance==null){
			synchronized (lock){
				if(instance==null){
					instance=new DynamicDataSource();
				}
			}
		}
		return instance;
	}
	//必须实现其方法
	protected Object determineCurrentLookupKey() {
		return DataSourceContextHolder.getDBType();
	}
}

4.DataSourceContextHolder

public class DataSourceContextHolder {
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

	public static synchronized void setDBType(String dbType){
		contextHolder.set(dbType);
	}

	public static String getDBType(){
		return contextHolder.get();
	}

	public static void clearDBType(){
		contextHolder.remove();
	}
}

5.DataSourceConfig

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class DataSourceConfig {

	@Value("${spring.datasource.acct.url}")
	private String acctDBUrl;
	@Value("${spring.datasource.acct.username}")
	private String acctDBUser;
	@Value("${spring.datasource.acct.password}")
	private String acctDBPassword;
	@Value("${spring.datasource.acct.driver-class-name}")
	private String acctDBDriverName;


	@Value("${spring.datasource.sett.url}")
	private String settDBUrl;
	@Value("${spring.datasource.sett.username}")
	private String settDBUser;
	@Value("${spring.datasource.sett.password}")
	private String settDBPassword;
	@Value("${spring.datasource.sett.driver-class-name}")
	private String settDBDriverName;

	@Bean
	public DynamicDataSource dynamicDataSource() {
		DynamicDataSource dynamicDataSource = DynamicDataSource.getInstance();

		DruidDataSource acctDataSource = new DruidDataSource();
		acctDataSource.setUrl(acctDBUrl);
		acctDataSource.setUsername(acctDBUser);
		acctDataSource.setPassword(acctDBPassword);
		acctDataSource.setDriverClassName(acctDBDriverName);

		DruidDataSource settDataSource = new DruidDataSource();
		settDataSource.setDriverClassName(settDBDriverName);
		settDataSource.setUrl(settDBUrl);
		settDataSource.setUsername(settDBUser);
		settDataSource.setPassword(settDBPassword);

		Map<Object, Object> map = new HashMap<>();
		map.put("acct", acctDataSource);
		map.put("sett", settDataSource);

		dynamicDataSource.setTargetDataSources(map);
		//默认数据源
		dynamicDataSource.setDefaultTargetDataSource(settDataSource);

		return dynamicDataSource;
	}

}

6.使用

DataSourceContextHolder.setDBType("acct");