java - 在外部 Spring Boot 配置中定义任意数量的数据源
问题描述
我有一个提供不同类型数据的 Spring Boot Web 服务,其中每种类型都驻留在自己的数据库中。随着新类型的添加,我不想在代码中为每种类型配置数据源。这是我到目前为止所得到的:
数据类型及其数据库连接定义在application.yml
:
datatypes:
someType:
url: jdbc:postgresql://mydatabase.com:5432/some_type
username: user1
password: pass1
otherType:
url: jdbc:postgresql://mydatabase.com:5432/other_type
username: user2
password: pass2
配置类读取属性并创建DataSource
s 和JdbcTemplate
s:
@Configuration
@EnableConfigurationProperties
public class JdbcConfig {
@Bean
@ConfigurationProperties(prefix = "datatypes")
public Map<String, DataSourceProperties> databaseConfig() {
return new HashMap<>();
}
@Bean
public Map<String, NamedParameterJdbcTemplate> jdbcTemplateMap() {
Map<String, DataSourceProperties> databaseConfig = databaseConfig();
Map<String, DataSource> dataSourceMap = databaseConfig().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry ->
entry.getValue().initializeDataSourceBuilder().build()));
return dataSourceMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry ->
new NamedParameterJdbcTemplate(entry.getValue())));
}
}
最后是一个根据其类型获取数据的存储库:
@Repository
public class MyRepository {
@Autowired
private Map<String, NamedParameterJdbcTemplate> jdbcTemplateMap;
public Item getItem(String dataType, String id) {
String sql = "select * from item where id = :id";
return jdbcTemplateMap.get(dataType)
.queryForObject(sql, Map.of("id", id), new ItemRowMapper());
}
}
当 Spring 尝试jdbcTemplateMap
在存储库中自动装配时,它找不到任何 jdbc 模板 bean,因此自动配置启动但失败,因为数据源的属性不在 yml 中的预期位置。这可以通过禁用自动配置来解决:@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
这个设置几乎可以工作。但是,由于DataSource
实例未在应用程序上下文中注册,因此我错过了其他一些自动配置魔法,例如执行器健康检查。我尝试自己注册它们,方法是将其添加到bean 方法并从该方法JdbcConfig
调用:registerDataSource()
jdbcTemplateMap()
@Autowired
private ApplicationContext applicationContext;
private void registerDataSource(String beanName, DataSource dataSource) {
ConfigurableApplicationContext context =
(ConfigurableApplicationContext) applicationContext;
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton(beanName, dataSource);
}
有了这个,我应该能够再次启用数据源自动配置,但它在jdbcTemplateMap()
有机会运行之前运行。执行器也不会拾取它们。这可以解决吗?
解决方案
推荐阅读
- javascript - 全高英雄背景图像在移动滚动上调整大小
- assembly - 用汇编语言“显示”换行符或回车符
- c++ - 堆栈反向 poish 计算器
- python - Python中的全局变量问题
- mysql - sql - 查询将 2 个表与 1 个表连接
- django - Django创建数据库视图,在列之间进行乘法,取平均值并按时间分组
- nginx - 通过 Nginx 反向代理连接到 Apache OpenMeetings 时遇到问题
- laravel - Laravel 7 路由问题
- matlab - 如何在 MATLAB 中减少图像匹配代码的运行时间?
- android - 创建服务以在后台运行并创建通知