如何使用Spring @Value从java属性文件中填充HashMap

2022-08-31 16:34:39

是否可以使用Spring @Value,将值从属性文件映射到HashMap。

目前我有这样的东西,映射一个值不是问题。但是我需要在HashMap到期中映射自定义值。这样的事情可能吗?

@Service
@PropertySource(value = "classpath:my_service.properties")
public class SomeServiceImpl implements SomeService {


    @Value("#{conf['service.cache']}")
    private final boolean useCache = false;

    @Value("#{conf['service.expiration.[<custom name>]']}")
    private final HashMap<String, String> expirations = new HashMap<String, String>();

属性文件:“my_service。

service.cache=true
service.expiration.name1=100
service.expiration.name2=20

是否可以像这样映射键:值集

  • name1 = 100

  • 名称2 = 20


答案 1

您可以使用类似 SPEL json 的语法在属性文件中编写简单映射或列表映射。

simple.map={'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}

map.of.list={\
  'KEY1': {'value1','value2'}, \
  'KEY2': {'value3','value4'}, \
  'KEY3': {'value5'} \
 }

我用于多行属性以增强可读性\

然后,在Java中,您可以使用如下方式自动访问和解析它。@Value

@Value("#{${simple.map}}")
Map<String, String> simpleMap;

@Value("#{${map.of.list}}")
Map<String, List<String>> mapOfList;

此处为 ,从属性文件中获取以下字符串:${simple.map}@Value

"{'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}"

然后,像内联一样对其进行评估

@Value("#{{'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}}")

您可以在官方文档中了解更多信息


答案 2

是否可以使用Spring @Value,将属性文件中的值映射到HashMap?

是的,它是。在代码和Spel的一点帮助下。

首先,考虑这个单例Spring-bean(你应该扫描它):

@Component("PropertySplitter")
public class PropertySplitter {

    /**
     * Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2
     */
    public Map<String, String> map(String property) {
        return this.map(property, ",");
    }

    /**
     * Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2
     */
    public Map<String, List<String>> mapOfList(String property) {
        Map<String, String> map = this.map(property, ";");

        Map<String, List<String>> mapOfList = new HashMap<>();
        for (Entry<String, String> entry : map.entrySet()) {
            mapOfList.put(entry.getKey(), this.list(entry.getValue()));
        }

        return mapOfList;
    }

    /**
     * Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4
     */
    public List<String> list(String property) {
        return this.list(property, ",");
    }

    /**
     * Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2
     */
    public List<List<String>> groupedList(String property) {
        List<String> unGroupedList = this.list(property, ";");

        List<List<String>> groupedList = new ArrayList<>();
        for (String group : unGroupedList) {
            groupedList.add(this.list(group));
        }

        return groupedList;

    }

    private List<String> list(String property, String splitter) {
        return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property);
    }

    private Map<String, String> map(String property, String splitter) {
        return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property);
    }

}

注意:类使用番石榴的实用程序。有关更多详细信息,请参阅其文档PropertySplitterSplitter

然后,在你的一些豆子里:

@Component
public class MyBean {

    @Value("#{PropertySplitter.map('${service.expiration}')}")
    Map<String, String> propertyAsMap;

}

最后,属性:

service.expiration = name1:100,name2:20

这并不完全是您所要求的,因为这适用于转换为 的单个属性,但我认为您可以切换到这种指定属性的方式,或者修改代码以使其与您想要的更具层次结构的方式相匹配。PropertySplitterMapPropertySplitter


推荐