如何在java spring中读取具有相同前缀的多个属性?

时间:2017-12-18 17:06:30

标签: java spring spring-mvc spring-boot

我正在使用具有以下值的属性文件。我想使用spring mvc读取所有具有相同前缀的属性,不包括其他属性。

test.cat = cat
test.dog =狗
test.cow =牛
鸟类=鹰

Environment.getProperty("test.cat");

这将只返回“猫”。 。

在上面的属性文件中,我希望使用 test (不包括鸟类)获取所有属性的开头(前缀)。在spring boot中我们可以使用@ConfigurationProperties(prefix="test")实现这一点,但是如何在spring mvc中实现相同的功能。

3 个答案:

答案 0 :(得分:4)

请参阅Spring项目中的Jira ticket,了解为什么您没有看到方法正在执行您想要的操作。可以像这样修改上述链接的片段,在最里面的循环中使用if语句进行过滤。我假设您有一个Environment env变量,正在寻找String prefix

Map<String, String> properties = new HashMap<>();
if (env instanceof ConfigurableEnvironment) {
    for (PropertySource<?> propertySource : ((ConfigurableEnvironment) env).getPropertySources()) {
        if (propertySource instanceof EnumerablePropertySource) {
            for (String key : ((EnumerablePropertySource) propertySource).getPropertyNames()) {
                if (key.startsWith(prefix)) {
                    properties.put(key, propertySource.getProperty(key));
                }
            }
        }
    }
}

答案 1 :(得分:1)

使用现有的API还有更雄辩的解决方案:

给出以下简单对象:

internal class AboutApi {
    lateinit var purpose: String
    lateinit var version: String
    lateinit var copyright: String
    lateinit var notice: String
    lateinit var contact: String
    lateinit var description: String
}

作为Spring环境(org.springframework.core.env.Environment的一个实例,从环境中提取AboutApi的值变得像1-2-3一样容易:

private fun about() : AboutApi {
    val binder = Binder.get(env)                   // Step - 1 
    val target = Bindable.ofInstance(AboutApi())   // Step - 2
    binder.bind("api.about", target)               // Step - 3
    return target.value.get()                      // Finally!
}
  1. 获取一个从环境中获取值的活页夹。
  2. 声明要绑定到的目标。
  3. 绑定环境中从api.about到目标的所有密钥。

最后-

获取值!

答案 2 :(得分:0)

我遇到了类似的问题,并使用以下代码解决了该问题:

final var keyPrefix = "test";
final var map = new HashMap<String, Object>();
final var propertySources = ((AbstractEnvironment) environment).getPropertySources().stream().collect(Collectors.toList());
Collections.reverse(propertySources);
for (PropertySource<?> source : propertySources) {
    if (source instanceof MapPropertySource) {
        final var mapProperties = ((MapPropertySource) source).getSource();
        mapProperties.forEach((key, value) -> {
            if (key.startsWith(keyPrefix)) {
                map.put(key, value instanceof OriginTrackedValue ? ((OriginTrackedValue) value).getValue() : value);
            }
        });
    }
}
return map;

与其他解决方案的区别(如在Jira ticket中看到的)是我对属性源进行了反向排序,以确保发生适当的属性覆盖。默认情况下,属性源从最重要到最不重要(也请参见此article)。因此,如果您在迭代之前不反转列表,则总会得到最不重要的属性值。