Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何用Spring@Value填充java属性文件中的HashMap_Java_Spring_Properties File_Spring El - Fatal编程技术网

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

如何用Spring@Value填充java属性文件中的HashMap,java,spring,properties-file,spring-el,Java,Spring,Properties File,Spring El,是否可以使用Spring@Value将属性文件中的值映射到HashMap 目前我有类似的东西,映射一个值不是问题。 但是我需要在HashMapExpirations中映射自定义值。 这样的事情可能吗 @Service @PropertySource(value = "classpath:my_service.properties") public class SomeServiceImpl implements SomeService { @Value("#{conf['servic

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

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

@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>();
是否可以像这个键:值集那样映射

  • 名称1=100

  • 名称2=20

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

是的。在代码和代码的帮助下

首先,考虑这个单弹簧bean(你应该扫描它):

最后,财产:

service.expiration = name1:100,name2:20

这并不完全是您所要求的,因为这个
PropertySplitter
与一个单独的属性一起工作,该属性被转换为
Map
,但我认为您可以切换到这种指定属性的方式,或者修改
PropertySplitter
代码,使其与您所希望的更层次化的方式相匹配。

我从上一篇文章中得到启发,提出了一个解决方案

在Spring配置中注册属性文件:

<util:properties id="myProp" location="classpath:my.properties"/>

我创建了一个组件:

@Component("PropertyMapper")
public class PropertyMapper {

    @Autowired
    ApplicationContext applicationContext;

    public HashMap<String, Object> startWith(String qualifier, String startWith) {
        return startWith(qualifier, startWith, false);
    }

    public HashMap<String, Object> startWith(String qualifier, String startWith, boolean removeStartWith) {
        HashMap<String, Object> result = new HashMap<String, Object>();

        Object obj = applicationContext.getBean(qualifier);
        if (obj instanceof Properties) {
            Properties mobileProperties = (Properties)obj;

            if (mobileProperties != null) {
                for (Entry<Object, Object> e : mobileProperties.entrySet()) {
                    Object oKey = e.getKey();
                    if (oKey instanceof String) {
                        String key = (String)oKey;
                        if (((String) oKey).startsWith(startWith)) {
                            if (removeStartWith) 
                                key = key.substring(startWith.length());
                            result.put(key, e.getValue());
                        }
                    }
                }
            }
        }

        return result;
    }
}
@组件(“PropertyMapper”)
公共类属性映射器{
@自动连线
应用上下文应用上下文;
公共HashMap startWith(字符串限定符,字符串startWith){
返回startWith(限定符,startWith,false);
}
公共HashMap startWith(字符串限定符、字符串startWith、布尔removeStartWith){
HashMap结果=新建HashMap();
objectobj=applicationContext.getBean(限定符);
if(属性的obj实例){
属性移动属性=(属性)对象;
if(mobileProperties!=null){
对于(条目e:mobileProperties.entrySet()){
对象oKey=e.getKey();
if(oKey instanceof String){
字符串键=(字符串)OK;
if((字符串)ok.startsWith(startWith)){
如果(使用removeStartWith)
key=key.substring(startWith.length());
result.put(key,e.getValue());
}
}
}
}
}
返回结果;
}
}
当我想将所有以specifix value开头的属性映射到HashMap时,使用@value注释:

@Service
public class MyServiceImpl implements MyService {

    @Value("#{PropertyMapper.startWith('myProp', 'service.expiration.', true)}")
    private HashMap<String, Object> portalExpirations;
@服务
公共类MyServiceImpl实现了MyService{
@值(“#{PropertyMapper.startWith('myProp','service.expiration',true)}”)
私有HashMap端口盗版;

我能想到的基于Spring引导的最快解决方案如下。在我的特定示例中,我正在将数据从一个系统迁移到另一个系统。这就是为什么我需要一个名为priority的字段的映射

首先,我创建了如下属性文件(priority migration.properties):

my.prefix.priority.0:0
my.prefix.priority.10:1
my.prefix.priority.15:2
my.prefix.priority.20:2
another.prefix.foo:bar
并将其放在类路径上

假设您希望在spring管理的bean/组件中使用映射,请使用以下注释注释您的类:

@Component
@PropertySource("classpath:/priority-migration.properties")
当然,您在地图中实际需要的只是以my.prefix为前缀的键/值对,即这部分:

{
    0:0
    10:1
    15:2
    20:2
}
要实现这一点,您需要使用

@ConfigurationProperties("my.prefix")
并为priority中缀创建一个getter。在我的例子中,后者被证明是强制性的(尽管声明有一个priority属性并用可变值初始化它就足够了)

private final Map priorityMap=new HashMap();
公共映射getPriority(){
返回优先映射;
}

最后

它看起来像这样:

@Component
@ConfigurationProperties("my.prefix")
@PropertySource("classpath:/priority-migration.properties")
class PriorityProcessor {

    private final Map<Integer, Integer> priorityMap = new HashMap<>();

    public Map<Integer, Integer> getPriority() {
        return priorityMap;
    }

    public void process() {

        Integer myPriority = priorityMap.get(10)
        // use it here
    }
}
@组件
@ConfigurationProperties(“my.prefix”)
@PropertySource(“类路径:/priority migration.properties”)
类优先级处理器{
private final Map priorityMap=new HashMap();
公共映射getPriority(){
返回优先映射;
}
公共程序(){
整数myPriority=priorityMap.get(10)
//在这里使用它
}
}
从Spring 4.1.x(我不记得具体的版本了),您可以执行以下操作

@Value("#{${your.properties.key.name}}")
private Map<String, String> myMap;
your.properties.key.name={\
    name1 : 100, \
    name2 : 200 \
}

只要确保您应该创建PropertySourcesPlaceHolderConfigurerBean,使其在应用程序中工作,并且如果您正在编写任何单元测试代码来测试代码,则${…}属性值的占位符将无法按预期工作,您将看到一些奇怪的SpringEL错误。

您可以使用类似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;
然后,对其进行评估,就好像它是内联的一样

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

您可以在应用程序.yml属性编码为多行的中使用@Value拉取地图的解决方案中了解更多信息

application.yml

这里,地图属性“my map property name”的值以JSON格式存储在字符串中,我们在行尾使用\实现了多行

myJavaClass.java

import org.springframework.beans.factory.annotation.Value;
公共类myJavaClass{
@值(“#{${my map property name}}”)
私人地图myMap;
公共方法(){
if(myMap.containsKey(“键1”)){
//待办事项。。。
} }
}
更多解释

  • \在yaml中,它用于将字符串拆分为多行

  • \“是yaml字符串中“(引号)的转义字符

  • {key:value}yaml中的JSON,将通过@value转换为映射

  • #{}它是SpEL表达式,可以在@Value to c中使用
    your.properties.key.name={\
        name1 : 100, \
        name2 : 200 \
    }
    
    simple.map={'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}
    
    map.of.list={\
      'KEY1': {'value1','value2'}, \
      'KEY2': {'value3','value4'}, \
      'KEY3': {'value5'} \
     }
    
    @Value("#{${simple.map}}")
    Map<String, String> simpleMap;
    
    @Value("#{${map.of.list}}")
    Map<String, List<String>> mapOfList;
    
    "{'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}"
    
    @Value("#{{'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}}")
    
    other-prop: just for demo 
    
    my-map-property-name: "{\
             key1: \"ANY String Value here\", \  
             key2: \"any number of items\" , \ 
             key3: \"Note the Last item does not have comma\" \
             }"
    
    other-prop2: just for demo 2 
    
    import org.springframework.beans.factory.annotation.Value;
    
    public class myJavaClass {
    
    @Value("#{${my-map-property-name}}") 
    private Map<String,String> myMap;
    
    public void someRandomMethod (){
        if(myMap.containsKey("key1")) {
                //todo...
        } }
    
    }
    
    private final HashMap<String, String> expiration 
    
    private final HashMap<String, String> expirations