2015-02-06 109 views
22

是否可以使用Spring @Value將屬性文件中的值映射到HashMap。如何使用Spring @Value從java屬性文件填充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.properties'

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

它是更多鈔票來圖來樣此項:值設置

  • 名1 = 100

  • 名稱2 = 20

+0

新和春豆廠是正交的。新的意思是「沒有彈簧」 – duffymo 2015-02-06 15:49:24

+0

@duffymo不能這樣概括。新的實體,新的ValueObject不在此 – madhairsilence 2016-12-20 12:16:20

回答

13

我在上一篇文章的啓發下做出了一個解決方案。在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; 
    } 
} 

當我想與specifix值HashMap中開頭的所有屬性映射,與@Value註釋:

@Service 
public class MyServiceImpl implements MyService { 

    @Value("#{PropertyMapper.startWith('myProp', 'service.expiration.', true)}") 
    private HashMap<String, Object> portalExpirations; 
17

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

是的。有一點代碼和Spel的幫助。

首先,考慮這單春豆(你應該對其進行掃描):

@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); 
    } 

} 

注:PropertySplitter類使用Splitter實用番石榴。詳情請參閱its documentation

然後,在你的一些豆:

@Component 
public class MyBean { 

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

} 

最後,屬性:

service.expiration = name1:100,name2:20 

這不是你問什麼,因爲這PropertySplitter作品與一個單一的屬性, 轉換成Map,但我認爲你可以切換到這種指定屬性的方式,或修改PropertySplitter代碼,以便它匹配更多層次的方式慾望。

3

最快的春天啓動我可以想到下面的基於的解決方案。在我特別的例子中,我將數據從一個系統遷移到另一個系統。這就是爲什麼我需要一個名爲優先的字段的映射。

首先我創建了屬性文件(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 

,並把它放在classpath。

假設你想使用彈簧託管bean /組件的地圖,與註釋類:

@Component 
@PropertySource("classpath:/priority-migration.properties") 

你真的想在你的地圖是什麼,當然只有那些前綴的鍵/值對與my.prefix,即這一部分:

{ 
    0:0 
    10:1 
    15:2 
    20:2 
} 

爲了實現這個目標,你需要註釋你的組件

@ConfigurationProperties("my.prefix") 

併爲優先中綴創建一個吸氣劑。後者被證明是在我的情況下,強制性的(雖然Sring Doc說,這是足有一個屬性優先和帶可變值初始化)

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

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

在結束

看起來像這樣:

@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 
    } 
} 
+0

'@ ConfigurationProperties'是Spring Boot註釋,而不是Spring註釋 – 2017-11-17 16:39:24

相關問題