从属性文件中读取列表并使用Spring注释@Value加载


244

我想在.properties文件中有一个值列表,即:

my.list.of.strings=ABC,CDE,EFG

并将其直接加载到我的课程中,即:

@Value("${my.list.of.strings}")
private List<String> myList;

据我了解,这样做的另一种方法是将其保存在spring config文件中,并将其作为bean引用加载(如果我错了,请更正我),即

<bean name="list">
 <list>
  <value>ABC</value>
  <value>CDE</value>
  <value>EFG</value>
 </list>
</bean>

但是有什么办法吗?使用.properties文件?ps:如果可能的话,我希望没有任何自定义代码。

Answers:


451

使用Spring EL:

@Value("#{'${my.list.of.strings}'.split(',')}") 
private List<String> myList;

假设使用以下内容正确加载了属性文件:

my.list.of.strings=ABC,CDE,EFG

1
我使用与您使用的相同的版本再次检查了它。完全按照帖子中的内容复制Spring EL,并且可以正常工作。但是不同的是,如果我在EL中出错,我会得到org.springframework.expression.spel.SpelEvaluationException异常而不是javax.el.ELException。您反对的对象是Spring吗?
Wilhelm Kleu 2012年

1
与Spring 3.2完美配合。
ehsanullahjan 2013年

17
空的财产my.list.of.strings=怎么样?我希望这样的功能会在此处将其变成一项(空字符串)的情况下重排空列表,不是吗?
2014年

5
还要注意,建议的解决方案不会进行修整,因此类似的值item1, item2, item3可能会给您带来您真正不希望的结果(提示:空格)。
2015年

4
如果您需要修剪空白,请使用正则表达式作为拆分参数..像@Value("#{'${my.list.of.strings}'.split(',\\s*')}")
Stackee007

88

从Spring 3.0开始,您可以添加一行

<bean id="conversionService" 
    class="org.springframework.context.support.ConversionServiceFactoryBean" />

到您的applicationContext.xml(或您配置的地方)。正如Dmitry Chornyi在评论中指出的那样,基于Java的配置看起来像:

@Bean public ConversionService conversionService() {
    return new DefaultConversionService();
}

这将激活支持转换StringCollection类型的新配置服务。如果您不激活此配置服务,Spring将退回其旧版属性编辑器作为配置服务,这些编辑器不支持这种转换。

转换为其他类型的集合也可以:

@Value("${my.list.of.ints}")
private List<Integer> myList

将与像

 my.list.of.ints= 1, 2, 3, 4

那里的空格没有问题,请多多ConversionServiceFactoryBean关照。

参见http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#core-convert-Spring-config

在Spring应用程序中,通常会为每个Spring容器(或ApplicationContext)配置一个ConversionService实例。Spring将获取该ConversionService,然后在框架需要执行类型转换时使用它。[...]如果未向Spring注册任何ConversionService,则使用原始的基于PropertyEditor的系统。


6
Java配置:@Bean public ConversionService conversionService(){return new DefaultConversionService(); }
德米特里·霍尼

2
除了避免split()在每个表达式中重复自己之外,它还正确地处理了一个空列表而不是给您[null]
Didier L

它不工作,如果物业overrided(在多个属性源的存在。)
丹尼尔·哈日

47

如果您正在阅读此书,并且正在使用Spring Boot,则此功能还有1个选项

通常,对于现实情况,用逗号分隔的列表非常笨拙(有时甚至不可行,如果要在配置中使用逗号):

email.sendTo=somebody@example.com,somebody2@example.com,somebody3@example.com,.....

使用Spring Boot,您可以这样编写(索引从0开始):

email.sendTo[0]=somebody@example.com
email.sendTo[1]=somebody2@example.com
email.sendTo[2]=somebody3@example.com

并像这样使用它:

@Component
@ConfigurationProperties("email")
public class EmailProperties {

    private List<String> sendTo;

    public List<String> getSendTo() {
        return sendTo;
    }

    public void setSendTo(List<String> sendTo) {
        this.sendTo = sendTo;
    }

}


@Component
public class EmailModel {

  @Autowired
  private EmailProperties emailProperties;

  //Use the sendTo List by 
  //emailProperties.getSendTo()

}



@Configuration
public class YourConfiguration {
    @Bean
  public EmailProperties emailProperties(){
        return new EmailProperties();
  }

}


#Put this in src/main/resource/META-INF/spring.factories
  org.springframework.boot.autoconfigure.EnableAutoConfiguration=example.compackage.YourConfiguration

我有一个问题,由于无法识别转义的逗号,此处描述的其他解决方案不起作用。有没有办法在Spring 4中实现此解决方案?
sandrozbinden '18年

33

通过my.list.of.strings=ABC,CDE,EFG在.properties文件中指定并使用

@Value("${my.list.of.strings}") private String[] myString;

您可以获取字符串数组。并使用CollectionUtils.addAll(myList, myString),您可以获得字符串列表。


我只有第一个字符串“ ABC”
Osama Abdulsattar

19

您是否考虑@Autowired过构造函数或二传手并String.split()在正文中输入?

class MyClass {
    private List<String> myList;

    @Autowired
    public MyClass(@Value("${my.list.of.strings}") final String strs) {
        myList = Arrays.asList(strs.split(","));
    }

    //or

    @Autowired
    public void setMyList(@Value("${my.list.of.strings}") final String strs) {
        myList = Arrays.asList(strs.split(","));
    }
}

我倾向于以以下一种方式进行自动装配,以增强代码的可测试性。


13

如果您使用的是Spring Boot 2,则无需任何其他配置即可直接使用。

my.list.of.strings=ABC,CDE,EFG

@Value("${my.list.of.strings}")
private List<String> myList;

不适用于我,我必须使用上面显示的Spring EL。
Bilbo Baggins,

甚至private List<String> myList;
Halayem阿尼斯

是的,它也对我
有用

8

以上所有答案都是正确的。但是您只需一行就可以实现。请尝试遵循以下声明,您将在字符串列表中获得所有逗号分隔的值。

private @Value("#{T(java.util.Arrays).asList(projectProperties['my.list.of.strings'])}") List<String> myList;

而且,您还需要在xml配置中定义以下行。

<util:properties id="projectProperties" location="/project.properties"/>

只需替换属性文件的路径和文件名即可。而且你很好。:)

希望这对您有帮助。干杯。


1
这对我有用,但是我必须这样标注注释:@Value("#{T(java.util.Arrays).asList('${my.list.of.strings}')}")
Steven

6

如果您使用的是最新的Spring框架版本(我相信是Spring 3.1+),则不需要在SpringEL中进行字符串拆分,

只需在Spring的Configuration类(带有Configuration注释的类)中添加PropertySourcesPlaceholderConfigurer和DefaultConversionService即可,例如,

@Configuration
public class AppConfiguration {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean public ConversionService conversionService() {
        return new DefaultConversionService();
    }
}

在你班上

@Value("${list}")
private List<String> list;

并在属性文件中

list=A,B,C,D,E

如果没有DefaultConversionService,则在将值注入字段时只能将逗号分隔的String放入String数组中,但是DefaultConversionService会为您提供一些方便的魔术,并将它们添加到Collection,Array等中。想了解更多信息)

有了这两个,它甚至可以处理所有多余的空白,包括换行符,因此您无需添加其他逻辑来修剪它们。


此配置的添加正在工作,但是发生了一些奇怪的事情:我无法将@Value用作文件类型,必须使用资源更改文件。
ad3luc

2

你可以用这样的注释来做到这一点

 @Value("#{T(java.util.Arrays).asList('${my.list.of.strings:a,b,c}')}") 
    private List<String> mylist;

这里my.list.of.strings将从属性文件中选取,如果不在该位置,则将使用默认值a,b,c

在您的属性文件中,您可以输入以下内容

my.list.of.strings = d,e,f


2

当心值中的空格。我可能是错的,但是我认为使用@Value和Spel不会将逗号分隔的列表中的空格截断。名单

foobar=a, b, c

将作为字符串列表读取

"a", " b", " c"

在大多数情况下,您可能不希望有空格!

表达方式

@Value("#{'${foobar}'.trim().replaceAll(\"\\s*(?=,)|(?<=,)\\s*\", \"\").split(',')}")
private List<String> foobarList;

会给你一个字符串列表:

"a", "b", "c".

正则表达式删除逗号之前和之后的所有空格。值内的空格不会删除。所以

foobar = AA, B B, CCC

应该导致价值

"AA", "B B", "CCC".

split()方法在内部使用正则表达式作为分隔符,因此可以简化您的示例:<br/>@Value("#{'${foobar}'.trim().split( *, *)}")
Karlik_B

2

我认为这对于获取数组和剥离空间更简单:

@Value("#{'${my.array}'.replace(' ', '').split(',')}")
private List<String> array;


1

考虑使用Commons Configuration。它具有内置功能,可将属性文件中的条目分解为数组/列表。结合SpEL和@Value应该可以提供您想要的


根据要求,这是您需要的(还没有真正尝试过代码,可能会有一些错别字,请多多包涵):

在Apache Commons Configuration中,有PropertiesConfiguration。它支持将定界字符串转换为数组/列表的功能。

例如,如果您有一个属性文件

#Foo.properties
foo=bar1, bar2, bar3

用下面的代码:

PropertiesConfiguration config = new PropertiesConfiguration("Foo.properties");
String[] values = config.getStringArray("foo");

会给你一个字符串数组 ["bar1", "bar2", "bar3"]

要与Spring一起使用,请在您的应用上下文xml中使用它:

<bean id="fooConfig" class="org.apache.commons.configuration.PropertiesConfiguration">
    <constructor-arg type="java.lang.String" value="classpath:/Foo.properties"/>
</bean>

并将其放入您的春豆中:

public class SomeBean {

    @Value("fooConfig.getStringArray('foo')")
    private String[] fooArray;
}

我相信这应该工作:P


您能否更详细地说明要使用的方法和类,并且实际的示例代码片段会很棒。
JackDev 2012年

1

我的首选方法(尤其是字符串)是以下一种方法:

admin.user={'Doe, John','Headroom, Max','Mouse, Micky'}

和使用

@Value("#{${admin.user}}")
private List<String> userList;

这样,您还可以在参数中包含逗号。它也适用于装置。


0

如果使用属性占位符,则ser1702544示例将变为

@Value("#{myConfigProperties['myproperty'].trim().replaceAll(\"\\s*(?=,)|(?<=,)\\s*\", \"\").split(',')}") 

使用占位符xml:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">   
    <property name="properties" ref="myConfigProperties" />
    <property name="placeholderPrefix"><value>$myConfigProperties{</value></property>
</bean>    

<bean id="myConfigProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
     <property name="locations">
         <list>
                <value>classpath:myprops.properties</value>
         </list>
     </property>
</bean> 

0

我正在使用Spring Boot 2.2.6

我的财产文件:

usa.big.banks= JP Morgan, Wells Fargo, Citigroup, Morgan Stanley, Goldman Sachs

我的代码:

@Value("${usa.big.banks}")
    private List<String> bigBanks;

@RequestMapping("/bigbanks")
    public String getBanks() {
        System.out.println("bigBanks = " + bigBanks);
        return bigBanks.toString();
    }

工作正常

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.