|
@@ -7,12 +7,10 @@ import java.util.Map;
|
|
|
import java.util.UUID;
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
import javax.sql.DataSource;
|
|
import javax.sql.DataSource;
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.MutablePropertyValues;
|
|
import org.springframework.beans.MutablePropertyValues;
|
|
|
import org.springframework.beans.PropertyValues;
|
|
import org.springframework.beans.PropertyValues;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -33,151 +31,154 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
* 动态数据源注册;
|
|
* 动态数据源注册;
|
|
|
*/
|
|
*/
|
|
|
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
|
|
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
|
|
|
-
|
|
|
|
|
- @Autowired
|
|
|
|
|
- JdbcTemplate jdbcTemplate;
|
|
|
|
|
-
|
|
|
|
|
- //如配置文件中未指定数据源类型,使用该默认值
|
|
|
|
|
- private static final Object DATASOURCE_TYPE_DEFAULT = "com.alibaba.druid.pool.DruidDataSource";
|
|
|
|
|
|
|
+
|
|
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceRegister.class);
|
|
|
|
|
+
|
|
|
|
|
+ // 如配置文件中未指定数据源类型,使用该默认值
|
|
|
|
|
+ private static final String DATASOURCE_TYPE_DEFAULT = "com.alibaba.druid.pool.DruidDataSource";
|
|
|
private ConversionService conversionService = new DefaultConversionService();
|
|
private ConversionService conversionService = new DefaultConversionService();
|
|
|
private PropertyValues dataSourcePropertyValues;
|
|
private PropertyValues dataSourcePropertyValues;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 默认数据源
|
|
// 默认数据源
|
|
|
private DataSource defaultDataSource;
|
|
private DataSource defaultDataSource;
|
|
|
-
|
|
|
|
|
- private Map<String, DataSource> customDataSources = new HashMap<String, DataSource>();
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 自定义数据源集合
|
|
|
|
|
+ private Map<String, DataSource> customDataSources = new HashMap<>();
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 加载多数据源配置
|
|
* 加载多数据源配置
|
|
|
*/
|
|
*/
|
|
|
@Override
|
|
@Override
|
|
|
public void setEnvironment(Environment environment) {
|
|
public void setEnvironment(Environment environment) {
|
|
|
- initDefaultDataSource(environment);
|
|
|
|
|
- initCustomDataSources(environment);
|
|
|
|
|
|
|
+ initDefaultDataSource(environment);
|
|
|
|
|
+ initCustomDataSources(environment);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
- * 加载主数据源配置.
|
|
|
|
|
- * @param env
|
|
|
|
|
|
|
+ * 初始化主数据源配置
|
|
|
*/
|
|
*/
|
|
|
- private void initDefaultDataSource(Environment env){
|
|
|
|
|
- // 读取主数据源
|
|
|
|
|
- RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "spring.datasource.");
|
|
|
|
|
-
|
|
|
|
|
- Map<String, Object> dsMap = new HashMap<String, Object>();
|
|
|
|
|
|
|
+ private void initDefaultDataSource(Environment env) {
|
|
|
|
|
+ logger.info("开始初始化默认数据源...");
|
|
|
|
|
+ RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "spring.datasource.");
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> dsMap = new HashMap<>();
|
|
|
dsMap.put("type", propertyResolver.getProperty("type"));
|
|
dsMap.put("type", propertyResolver.getProperty("type"));
|
|
|
dsMap.put("driverClassName", propertyResolver.getProperty("driverClassName"));
|
|
dsMap.put("driverClassName", propertyResolver.getProperty("driverClassName"));
|
|
|
dsMap.put("url", propertyResolver.getProperty("url"));
|
|
dsMap.put("url", propertyResolver.getProperty("url"));
|
|
|
dsMap.put("username", propertyResolver.getProperty("username"));
|
|
dsMap.put("username", propertyResolver.getProperty("username"));
|
|
|
dsMap.put("password", propertyResolver.getProperty("password"));
|
|
dsMap.put("password", propertyResolver.getProperty("password"));
|
|
|
-
|
|
|
|
|
- //创建数据源;
|
|
|
|
|
defaultDataSource = buildDataSource(dsMap);
|
|
defaultDataSource = buildDataSource(dsMap);
|
|
|
dataBinder(defaultDataSource, env);
|
|
dataBinder(defaultDataSource, env);
|
|
|
- customDataSources.put(propertyResolver.getProperty("username"), defaultDataSource);
|
|
|
|
|
|
|
+ logger.info("默认数据源初始化完成: {}", propertyResolver.getProperty("url"));
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
- * 初始化更多数据源
|
|
|
|
|
- *
|
|
|
|
|
|
|
+ * 初始化自定义数据源
|
|
|
*/
|
|
*/
|
|
|
private void initCustomDataSources(Environment env) {
|
|
private void initCustomDataSources(Environment env) {
|
|
|
- // 读取配置文件获取更多数据源,也可以通过defaultDataSource读取数据库获取更多数据源
|
|
|
|
|
- /*DynamicDataSourceManage.setDataSourceType("UAS_DEV");
|
|
|
|
|
- List<Map<String , Object>> master = jdbcTemplate.queryForList("select MA_USER,MA_PWD from master");
|
|
|
|
|
- System.out.println(master);*/
|
|
|
|
|
- JdbcTemplate jdbcTemplate = new JdbcTemplate(defaultDataSource);
|
|
|
|
|
- List<Map<String , Object>> master = jdbcTemplate.queryForList("select MA_USER,MS_PWD from master");
|
|
|
|
|
- // 读取主数据源
|
|
|
|
|
- RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "spring.datasource.");
|
|
|
|
|
- for(Map<String , Object> map : master){
|
|
|
|
|
- String ma_user = (String)map.get("MA_USER");
|
|
|
|
|
- Map<String, Object> dsMap = new HashMap<>();
|
|
|
|
|
- dsMap.put("type", propertyResolver.getProperty("type"));
|
|
|
|
|
- dsMap.put("driverClassName", propertyResolver.getProperty("driverClassName"));
|
|
|
|
|
- dsMap.put("url", propertyResolver.getProperty("url"));
|
|
|
|
|
- dsMap.put("password", propertyResolver.getProperty("password"));
|
|
|
|
|
- dsMap.put("username", ma_user);
|
|
|
|
|
- DataSource ds = buildDataSource(dsMap);
|
|
|
|
|
- customDataSources.put(ma_user, ds);
|
|
|
|
|
- dataBinder(ds, env);
|
|
|
|
|
- }
|
|
|
|
|
- /*RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "custom.datasource.");
|
|
|
|
|
|
|
+ logger.info("开始初始化自定义数据源...");
|
|
|
|
|
+ RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "custom.datasource.");
|
|
|
String dsPrefixs = propertyResolver.getProperty("names");
|
|
String dsPrefixs = propertyResolver.getProperty("names");
|
|
|
- for (String dsPrefix : dsPrefixs.split(",")) {// 多个数据源
|
|
|
|
|
- Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix + ".");
|
|
|
|
|
- DataSource ds = buildDataSource(dsMap);
|
|
|
|
|
- customDataSources.put(dsPrefix, ds);
|
|
|
|
|
- dataBinder(ds, env);
|
|
|
|
|
- }*/
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (dsPrefixs != null && !dsPrefixs.isEmpty()) {
|
|
|
|
|
+ logger.info("检测到自定义数据源配置: {}", dsPrefixs);
|
|
|
|
|
+ for (String dsPrefix : dsPrefixs.split(",")) {
|
|
|
|
|
+ Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix + ".");
|
|
|
|
|
+ if (!dsMap.isEmpty()) {
|
|
|
|
|
+ logger.info("正在初始化数据源: {}", dsPrefix);
|
|
|
|
|
+ DataSource ds = buildDataSource(dsMap);
|
|
|
|
|
+ if (ds != null) {
|
|
|
|
|
+ customDataSources.put(dsPrefix, ds);
|
|
|
|
|
+ dataBinder(ds, env);
|
|
|
|
|
+ logger.info("数据源 [{}] 初始化完成: {}", dsPrefix, dsMap.get("url"));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ logger.warn("未检测到自定义数据源配置");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
- * 创建datasource.
|
|
|
|
|
- * @param dsMap
|
|
|
|
|
- * @return
|
|
|
|
|
|
|
+ * 创建数据源实例
|
|
|
*/
|
|
*/
|
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
|
public DataSource buildDataSource(Map<String, Object> dsMap) {
|
|
public DataSource buildDataSource(Map<String, Object> dsMap) {
|
|
|
- Object type = dsMap.get("type");
|
|
|
|
|
- if (type == null){
|
|
|
|
|
- type = DATASOURCE_TYPE_DEFAULT;// 默认DataSource
|
|
|
|
|
|
|
+ Object type = dsMap.get("type");
|
|
|
|
|
+ if (type == null) {
|
|
|
|
|
+ type = DATASOURCE_TYPE_DEFAULT;
|
|
|
}
|
|
}
|
|
|
- Class<? extends DataSource> dataSourceType;
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
|
|
|
|
|
- String driverClassName = dsMap.get("driverClassName").toString();
|
|
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ Class<? extends DataSource> dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
|
|
|
|
|
+ String driverClassName = dsMap.get("driverClassName").toString();
|
|
|
String url = dsMap.get("url").toString();
|
|
String url = dsMap.get("url").toString();
|
|
|
String username = dsMap.get("username").toString();
|
|
String username = dsMap.get("username").toString();
|
|
|
String password = dsMap.get("password").toString();
|
|
String password = dsMap.get("password").toString();
|
|
|
- DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url).username(username).password(password).type(dataSourceType);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ DataSourceBuilder factory = DataSourceBuilder.create()
|
|
|
|
|
+ .driverClassName(driverClassName)
|
|
|
|
|
+ .url(url)
|
|
|
|
|
+ .username(username)
|
|
|
|
|
+ .password(password)
|
|
|
|
|
+ .type(dataSourceType);
|
|
|
|
|
+
|
|
|
return factory.build();
|
|
return factory.build();
|
|
|
- } catch (ClassNotFoundException e) {
|
|
|
|
|
- e.printStackTrace();
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
|
|
+ } catch (ClassNotFoundException e) {
|
|
|
|
|
+ logger.error("数据源类型类未找到: {}", dsMap.get("type"), e);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error("创建数据源失败", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
- * 为DataSource绑定更多数据
|
|
|
|
|
- * @param dataSource
|
|
|
|
|
- * @param env
|
|
|
|
|
|
|
+ * 为DataSource绑定更多配置属性
|
|
|
*/
|
|
*/
|
|
|
- private void dataBinder(DataSource dataSource, Environment env){
|
|
|
|
|
- RelaxedDataBinder dataBinder = new RelaxedDataBinder(dataSource);
|
|
|
|
|
- dataBinder.setConversionService(conversionService);
|
|
|
|
|
- dataBinder.setIgnoreNestedProperties(false);//false
|
|
|
|
|
- dataBinder.setIgnoreInvalidFields(false);//false
|
|
|
|
|
- dataBinder.setIgnoreUnknownFields(true);//true
|
|
|
|
|
-
|
|
|
|
|
- if(dataSourcePropertyValues == null){
|
|
|
|
|
|
|
+ private void dataBinder(DataSource dataSource, Environment env) {
|
|
|
|
|
+ RelaxedDataBinder dataBinder = new RelaxedDataBinder(dataSource);
|
|
|
|
|
+ dataBinder.setConversionService(conversionService);
|
|
|
|
|
+ dataBinder.setIgnoreNestedProperties(false);
|
|
|
|
|
+ dataBinder.setIgnoreInvalidFields(false);
|
|
|
|
|
+ dataBinder.setIgnoreUnknownFields(true);
|
|
|
|
|
+
|
|
|
|
|
+ if (dataSourcePropertyValues == null) {
|
|
|
Map<String, Object> values = new HashMap<>();
|
|
Map<String, Object> values = new HashMap<>();
|
|
|
dataSourcePropertyValues = new MutablePropertyValues(values);
|
|
dataSourcePropertyValues = new MutablePropertyValues(values);
|
|
|
}
|
|
}
|
|
|
dataBinder.bind(dataSourcePropertyValues);
|
|
dataBinder.bind(dataSourcePropertyValues);
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 注册动态数据源Bean
|
|
|
|
|
+ */
|
|
|
@Override
|
|
@Override
|
|
|
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
|
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
|
|
- Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
|
|
|
|
|
- // 将主数据源添加到更多数据源中
|
|
|
|
|
- /*targetDataSources.put("dataSource", defaultDataSource);
|
|
|
|
|
- DynamicDataSourceManage.dataSourceIds.add("dataSource");*/
|
|
|
|
|
- // 添加更多数据源
|
|
|
|
|
|
|
+ logger.info("========== 开始注册动态数据源 ==========");
|
|
|
|
|
+
|
|
|
|
|
+ Map<Object, Object> targetDataSources = new HashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 将所有自定义数据源添加到目标数据源映射中
|
|
|
targetDataSources.putAll(customDataSources);
|
|
targetDataSources.putAll(customDataSources);
|
|
|
- // 创建DynamicDataSource
|
|
|
|
|
|
|
+
|
|
|
|
|
+ logger.info("已注册的数据源列表: {}", targetDataSources.keySet());
|
|
|
|
|
+ logger.info("默认数据源将作为 fallback 使用");
|
|
|
|
|
+
|
|
|
|
|
+ // 创建DynamicDataSource Bean定义
|
|
|
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
|
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
|
|
beanDefinition.setBeanClass(DynamicDataSource.class);
|
|
beanDefinition.setBeanClass(DynamicDataSource.class);
|
|
|
-
|
|
|
|
|
beanDefinition.setSynthetic(true);
|
|
beanDefinition.setSynthetic(true);
|
|
|
|
|
+
|
|
|
MutablePropertyValues mpv = beanDefinition.getPropertyValues();
|
|
MutablePropertyValues mpv = beanDefinition.getPropertyValues();
|
|
|
- //添加属性:AbstractRoutingDataSource.defaultTargetDataSource
|
|
|
|
|
|
|
+ // 设置默认目标数据源(当SpObserver中没有设置数据源时使用)
|
|
|
mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource);
|
|
mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource);
|
|
|
|
|
+ // 设置所有可用的目标数据源
|
|
|
mpv.addPropertyValue("targetDataSources", targetDataSources);
|
|
mpv.addPropertyValue("targetDataSources", targetDataSources);
|
|
|
|
|
+
|
|
|
|
|
+ // 注册名为"dataSource"的Bean
|
|
|
registry.registerBeanDefinition("dataSource", beanDefinition);
|
|
registry.registerBeanDefinition("dataSource", beanDefinition);
|
|
|
|
|
+ logger.info("========== 动态数据源注册完成 ==========");
|
|
|
|
|
+ logger.info("可用数据源: {}", targetDataSources.keySet());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|