Spring - 如何在不枚举所有必需属性的情况下获取属性文件的子集
Spring - How to get subset of properties file without enumerating all required properties
我正在加载我的属性文件如下:
@Configuration
@PropertySource("classpath:app.properties")
class MyApp {
@Bean
public PropertySourcesPlaceholderConfigurer PropertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
在属性文件中,我有几个与数据库相关的属性:
database.dataSource.url=jdbc:postgresql://localhost:${db-port:5432}/mydb
database.dataSource.x=...
database.dataSource.y=...
database.dataSource.z=...
注:
${db-port}
应替换为 property/environment 变量 db-port
或 5432 的值。在我的例子中,我正在定义环境变量 db-port
生成 Tomcat 容器时。
所有与数据库相关的属性都分组在 database.
根下。这是故意的,见下文。
我想避免我必须 enumerate/hardcode 我的代码中所有可能的数据库相关属性。 幸运的是,正在使用的数据库层 (Hikari) 具有不错的功能,我可以通过 java.util.Properties
传递所有属性。所以,我想检索 database.*
下所有已定义的属性并将其简单地转发给 Hikari。
为此,我编写了以下实用程序:
@Component
public class PropertyFetcher
{
@Autowired
private ConfigurableEnvironment environment;
public Properties get(final String key) {
final Properties p = new Properties();
for (final PropertySource<?> s : environment.getPropertySources()) {
if (s instanceof EnumerablePropertySource) {
for (final String k : ((EnumerablePropertySource) s).getPropertyNames()) {
if (k.startsWith(key) && k.length() > key.length()) {
p.put(k.substring(key.length()), s.getProperty(k));
}
}
}
}
return p;
}
}
现在,当调用 get("database.")
时,我拥有属性文件中定义的所有数据库相关属性。伟大的!但是,属性 dataSource.url
的值现在是
jdbc:postgresql://localhost:${db-port:5432}/mydb
而不是
jdbc:postgresql://localhost:9876/mydb
因此,出于某种原因,${db-port:5432}
在通过这条路线 (ConfigurableEnvironment
) 时尚未解决(尚未?)。
如何解决这个问题?或者有没有更好的方法来获取某个根目录下的所有属性,而不必 enumerate/hardcode 它们进入代码?
请注意,在默认情况下,属性 database.dataSource.url=jdbc:postgresql://localhost:${db-port:5432}/mydb
中的 ${db-port:5432}
已正确解析。我通过定义以下成员并记录它来测试它:
@Value("${database.dataSource.url}")
final String url; // holds jdbc:postgresql://localhost:9876/mydb
您应该只从真实环境中读取 属性 值。然后只有你会得到一个 属性.
的实际或有效值
这需要对您的代码稍作更改。
更改此行:
p.put(k.substring(key.length()), s.getProperty(k));
对此:
p.put(k.substring(key.length()), environment.getProperty(k));
我正在加载我的属性文件如下:
@Configuration
@PropertySource("classpath:app.properties")
class MyApp {
@Bean
public PropertySourcesPlaceholderConfigurer PropertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
在属性文件中,我有几个与数据库相关的属性:
database.dataSource.url=jdbc:postgresql://localhost:${db-port:5432}/mydb
database.dataSource.x=...
database.dataSource.y=...
database.dataSource.z=...
注:
${db-port}
应替换为 property/environment 变量db-port
或 5432 的值。在我的例子中,我正在定义环境变量db-port
生成 Tomcat 容器时。所有与数据库相关的属性都分组在
database.
根下。这是故意的,见下文。
我想避免我必须 enumerate/hardcode 我的代码中所有可能的数据库相关属性。 幸运的是,正在使用的数据库层 (Hikari) 具有不错的功能,我可以通过 java.util.Properties
传递所有属性。所以,我想检索 database.*
下所有已定义的属性并将其简单地转发给 Hikari。
为此,我编写了以下实用程序:
@Component
public class PropertyFetcher
{
@Autowired
private ConfigurableEnvironment environment;
public Properties get(final String key) {
final Properties p = new Properties();
for (final PropertySource<?> s : environment.getPropertySources()) {
if (s instanceof EnumerablePropertySource) {
for (final String k : ((EnumerablePropertySource) s).getPropertyNames()) {
if (k.startsWith(key) && k.length() > key.length()) {
p.put(k.substring(key.length()), s.getProperty(k));
}
}
}
}
return p;
}
}
现在,当调用 get("database.")
时,我拥有属性文件中定义的所有数据库相关属性。伟大的!但是,属性 dataSource.url
的值现在是
jdbc:postgresql://localhost:${db-port:5432}/mydb
而不是
jdbc:postgresql://localhost:9876/mydb
因此,出于某种原因,${db-port:5432}
在通过这条路线 (ConfigurableEnvironment
) 时尚未解决(尚未?)。
如何解决这个问题?或者有没有更好的方法来获取某个根目录下的所有属性,而不必 enumerate/hardcode 它们进入代码?
请注意,在默认情况下,属性 database.dataSource.url=jdbc:postgresql://localhost:${db-port:5432}/mydb
中的 ${db-port:5432}
已正确解析。我通过定义以下成员并记录它来测试它:
@Value("${database.dataSource.url}")
final String url; // holds jdbc:postgresql://localhost:9876/mydb
您应该只从真实环境中读取 属性 值。然后只有你会得到一个 属性.
的实际或有效值这需要对您的代码稍作更改。
更改此行:
p.put(k.substring(key.length()), s.getProperty(k));
对此:
p.put(k.substring(key.length()), environment.getProperty(k));