项目中,数据迁移涉及到多个数据源,需要在代码里动态切换,且子工程需要在配置文件中配置多个数据源。有了如下配置:
改写后的数据源。加2个属性
@Data
public class LocalHikariDataSource extends HikariDataSource {
//多数据源配置时的名字
private String dataSourceName;
//是否默认数据源
private String isDefault;
}
数据源有区别的属性
@Data
public class DataSourceParam {
// 给数据源起的别外,用于切换数据源使用
private DataSourceName dataSourceName;
// jdbcurl
private String url;
// jdbc驱动名
private String driver;
// jdbc帐号
private String userName;
// jdbc密码
private String password;
// 是否默认数据源,多数据源默认的那个
private Boolean isDefault = false;
// 测试连接用的aql,如select 1,select 1 from dual
private String testSelectSql;
}
动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
@Autowired
List<LocalHikariDataSource> localHikariDataSources;
@Override
public void afterPropertiesSet() {
Map<Object, Object> targetDataSources = newHashMap();
for (LocalHikariDataSource dataSource : localHikariDataSources) {
if (dataSource.isDefault()) {
this.setDefaultTargetDataSource(dataSource);
}
targetDataSources.put(dataSource.getDataSourceName(), dataSource);
}
this.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return RouteThreadLocal.get();
}
}
属性配置类
@ConfigurationProperties(prefix = "com.datamove")
public class DataMoveProperties {
public List<DataSourceParam> sourceParams = new ArrayList<>();
public List<DataSourceParam> getSourceParams() {
return sourceParams;
}
public void setSourceParams(List<DataSourceParam> sourceParams) {
this.sourceParams = sourceParams;
}
}
配置类:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
/**
* @description 【多数据源配置】
* @author Simple-Zeng
* @DATE 2020年3月17日下午3:52:35
*/
@Configuration("dynamicDataSourceConfig")
@Profile("datamove")
public class DataMoveConfig implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
//此处是不能直接把DataMoveProperties 注入进来的,
//只能从环境里面去读取配置,注册bean会在初始化DataMoveProperties 之前执行。参考BeanDefinitionRegistryPostProcessor的执行时机
private Environment environment;
@Bean
@Primary
public DynamicDataSource createDynamicDataSource() {
return new DynamicDataSource();
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
for (int i = 0; i < 10; i++) {
String dataSourceName = getProperties(i, "data-source-name");
if (isNull(dataSourceName)) {
break;
}
String jdbcurl = getProperties(i, "url");
String driver = getProperties(i, "driver");
String userName = getProperties(i, "user-name");
String password = getProperties(i, "password");
String isDefault = getProperties(i, "is-default");
boolean isDefaultboo = Boolean.parseBoolean(isDefault);
String testSelectSql = getProperties(i, "test-select-sql");
BeanDefinitionBuilder rootBeanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(LocalHikariDataSource.class);
rootBeanDefinition.addPropertyValue("driverClassName", driver);
rootBeanDefinition.addPropertyValue("jdbcUrl", jdbcurl);
rootBeanDefinition.addPropertyValue("username", userName);
rootBeanDefinition.addPropertyValue("password", password);
rootBeanDefinition.addPropertyValue("dataSourceName", dataSourceName);
rootBeanDefinition.addPropertyValue("isDefault", isDefaultboo);
rootBeanDefinition.addPropertyValue("initializationFailTimeout", 600000);
rootBeanDefinition.addPropertyValue("connectionTestQuery", testSelectSql);
rootBeanDefinition.addPropertyValue("MinimumIdle", 5);
rootBeanDefinition.addPropertyValue("maximumPoolSize", 10);
rootBeanDefinition.addPropertyValue("autoCommit", true);
rootBeanDefinition.addPropertyValue("idleTimeout", 170000);
rootBeanDefinition.addPropertyValue("poolName", "DatebookHikariCP");
rootBeanDefinition.addPropertyValue("maxLifetime", 180000);
rootBeanDefinition.addPropertyValue("connectionTimeout", 20000);
registry.registerBeanDefinition(dataSourceName, rootBeanDefinition.getBeanDefinition());
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
private String getProperties(int i, String name) {
String key = "com.datamove.source-params[" + i + "]." + name;
return environment.getProperty(key);
}
}
com:
datamove:
sourceParams:
- dataSourceName: sourcedbDataSoucre
url: xxxxxxxxxxxxxxxxxxxxxxx
driver: xxxxxxxxxxxxxxxxxxxxxxx
userName: xxxxxxxxxxxxxxxxxxxxxxx
password: xxxxxxxxxxxxxxxxxxxxxxx
isDefault: true
testSelectSql: SELECT 1 FROM DUAL
- dataSourceName: targerdbDataSource1
url:xxxxxxxxxxxxxxxxxxxxxxx
driver: xxxxxxxxxxxxxxxxxxxxxxx
userName: xxxxxxxxxxxxxxxxxxxxxxx
password: xxxxxxxxxxxxxxxxxxxxxxx
isDefault: false
testSelectSql: select 1
- dataSourceName: targerdbDataSource2
url:xxxxxxxxxxxxxxxxxxxxxxx
driver: xxxxxxxxxxxxxxxxxxxxxxx
userName: xxxxxxxxxxxxxxxxxxxxxxx
password: xxxxxxxxxxxxxxxxxxxxxxx
isDefault: false
testSelectSql: select 1