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

3qpi33ja  于 2023-03-06  发布在  Java
关注(0)|答案(4)|浏览(199)

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

**试验猫=猫

test.dog狗
试验母牛=母牛
鸟=鹰**

Environment.getProperty("test.cat");

这将只返回“cat”。
在上面的属性文件中,我想获取以***test***开头(前缀)的所有属性,不包括birds。在spring Boot 中我们可以用@ConfigurationProperties(prefix="test")实现这一点,但是如何在spring mvc中实现同样的功能呢。

ttygqcqt

ttygqcqt1#

参见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));
                }
            }
        }
    }
}
dojqjjoe

dojqjjoe2#

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

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)。因此,如果在迭代之前不对列表进行反向排序,则最终总是得到最不重要的属性值。

dba5bblo

dba5bblo3#

使用现有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.获取一个从环境中获取值的绑定器。
1.声明要绑定到的目标。
1.将以api.about开头的环境中的所有键绑定到我们的目标。
最后--
找回价值!

pepwfjgg

pepwfjgg4#

尝试此方法。在示例中,调用getAllPropWithPrefix("test")将返回包含{test.cat=cat,test.dog=dog,test.cow=cow}的Map

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class SpringPropertiesUtil {

    @Autowired
    private ConfigurableApplicationContext applicationContext;

    /**
     * Get all properties with specific prefix. 
     */
    public Map<String,String> getAllPropWithPrefix(String prefix) {
        BindResult<Map<String, String>> result = Binder.get(applicationContext.getEnvironment())
                .bind(prefix, Bindable.mapOf(String.class, String.class));
        if (!result.isBound() || result.get()==null) {
            return Collections.emptyMap();
        }
        return result.get().entrySet().stream().collect(Collectors.toMap(x->prefix+"."+x.getKey(),x->x.getValue()));
    }
}

相关问题