2015-02-06 117 views
22

Có thể sử dụng Spring @Value không, để ánh xạ các giá trị từ tệp thuộc tính vào HashMap.Cách điền HashMap từ tệp thuộc tính java với Spring @Value

Hiện tại tôi có một cái gì đó như thế này và ánh xạ một giá trị không phải là vấn đề. Nhưng tôi cần ánh xạ các giá trị tùy chỉnh trong thời hạn HashMap. Có phải một cái gì đó như thế này có thể?

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

tập tin tài sản: 'my_service.properties'

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

Có posible để lập bản đồ như phím này: giá trị thiết lập

  • name1 = 100

  • name2 = 20

+0

Nhà máy sản xuất đậu mới và mùa xuân là trực giao. phương tiện mới "no Spring" – duffymo

+0

@duffymo không thể được khái quát hóa như thế. thực thể mới, ValueObject mới không có trong thuộc tính này – madhairsilence

Trả lời

13

Tôi tạo một giải pháp lấy cảm hứng từ bài đăng trước.

tập tin bất động sản đăng ký trong cấu hình Spring:

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

Và tôi có thể tạo thành phần:

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

Và khi tôi muốn để lập bản đồ tất cả các tính năng mà bắt đầu với giá trị specifix để HashMap, với @value chú thích:

@Service 
public class MyServiceImpl implements MyService { 

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

Có thể sử dụng Spring @Value không, để ánh xạ giá trị từ tệp thuộc tính vào HashMap?

Vâng, đúng vậy. Với một chút trợ giúp về mã và Spel.

Trước hết, hãy xem xét singleton mùa xuân-đậu này (bạn nên quét nó):

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

} 

Lưu ý:PropertySplitter lớp sử dụng Splitter tiện ích từ ổi. Vui lòng tham khảo its documentation để biết thêm chi tiết.

Sau đó, trong một số đậu của bạn:

@Component 
public class MyBean { 

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

} 

Và cuối cùng, bất động sản:

service.expiration = name1:100,name2:20 

Nó không chính xác những gì bạn đã hỏi, vì đây PropertySplitter làm việc với một tài sản duy nhất mà được chuyển đổi thành một số Map, nhưng tôi nghĩ bạn có thể chuyển sang cách chỉ định thuộc tính này hoặc sửa đổi mã PropertySplitter để mã khớp với cách phân cấp hơn khao khát.

3

Nhanh nhất mùa xuân Khởi động giải pháp dựa trên tôi có thể nghĩ về sau.Trong ví dụ cụ thể của tôi, tôi đang di chuyển dữ liệu từ hệ thống này sang hệ thống khác. Đó là lý do tại sao tôi cần ánh xạ cho một trường có tên là ưu tiên.

Đầu tiên tôi đã tạo ra các thuộc tính tập tin (priority-migration.properties) như ví dụ:

my.prefix.priority.0:0 
my.prefix.priority.10:1 
my.prefix.priority.15:2 
my.prefix.priority.20:2 
another.prefix.foo:bar 

và đặt nó trên classpath.

Giả sử bạn muốn sử dụng bản đồ trong một dòng suối quản lý đậu/thành phần, chú thích lớp học của bạn với:

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

gì bạn thực sự muốn trong bản đồ của bạn là tất nhiên chỉ các cặp khóa/giá trị đó được bắt đầu với my.prefix, tức là phần này:

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

để đạt được điều đó bạn cần phải chú thích thành phần của bạn với

@ConfigurationProperties("my.prefix") 

và tạo bộ thu thập cho ưu tiên ưu tiên. Sau này được chứng minh là bắt buộc trong trường hợp của tôi (mặc dù Sring Doc nói nó là đủ để có một ưu tiên sở hữu và khởi tạo nó với một giá trị có thể thay đổi)

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

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

In the End

Có dạng như sau:

@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' là chú thích Spring Boot, không phải là chú giải Spring –

Các vấn đề liên quan