如何用Spring@Value填充java属性文件中的HashMap
是否可以使用Spring@Value将属性文件中的值映射到HashMap 目前我有类似的东西,映射一个值不是问题。 但是我需要在HashMapExpirations中映射自定义值。 这样的事情可能吗如何用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
@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
首先,考虑这个单弹簧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