プロパティファイルからリストを読み取り、Springアノテーション@Valueでロードする


244

.propertiesファイルに値のリストを入れたい、つまり:

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

そしてそれを私のクラスに直接ロードするには、すなわち:

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

私が理解しているように、これを行う別の方法は、それをSpring構成ファイルに入れて、それをBean参照としてロードすることです(私が間違っている場合は修正してください)。

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

しかし、これを行う方法はありますか?.propertiesファイルを使用していますか?PS:可能であれば、カスタムコードなしでこれを実行したいと思います。

回答:


453

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=どうですか?私はそのような機能が空のリストを返すことを期待しますが、ここでは1つのアイテム(空の文字列)になりますね。
Jan Zyka 2014

5
また、提案されたソリューションはトリミングitem1, item2, item3を行わないので、などの値は実際には予期しない結果になる可能性があることに注意してください(ヒント:スペース)。
Jan Zyka

4
空のスペースをトリムする必要がある場合は、分割引数に正規表現を使用します。@Value("#{'${my.list.of.strings}'.split(',\\s*')}")
たとえば、

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

これにより、Stringへの変換をサポートする新しい構成サービスがアクティブになりますCollectionタイプます。この構成サービスをアクティブにしない場合、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インスタンスを構成します。そのConversionServiceはSpringによって取得され、フレームワークが型変換を実行する必要がある場合は常に使用されます。[...] SpringにConversionServiceが登録されていない場合、元のPropertyEditorベースのシステムが使用されます。


6
Java設定:@Bean public ConversionService conversionService(){return new DefaultConversionService(); }
ドミトリーチョンイイ2015年

2
split()すべての式で自分自身を繰り返すことを避ける以外に、それはあなたに与える代わりに空のリストを適切に処理します[null]
Didier L

プロパティがオーバーライドされている場合は機能しません(複数のプロパティソースに存在します)
DanielHári

47

これを読んでいて、Spring Bootを使用している場合、この機能にはもう1つのオプションがあります

通常、コンマで区切られたリストは、実際のユースケースでは非常に不格好です(構成でコンマを使用したい場合は、実行できない場合もあります)。

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

春ブーツ、あなたは(インデックスは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

34

my.list.of.strings=ABC,CDE,EFGin .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(","));
    }
}

私は、コードのテスト容易性を高めるために、これらの方法の1つで自動配線を行う傾向があります。


14

Spring Boot 2を使用している場合は、追加の構成を行わなくても、そのまま機能します。

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

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

うまくいきませんでした。上記のようにSpring ELを使用する必要があります。
ビルボバギンズ

またはさらにprivate List<String> myList;
Halayem Anis

はい、それは私にとってもうまくいきました:私はSpring Boot 2.2.6を使用しています
Ankit

8

上記の答えはすべて正しいです。しかし、これはたった1行で実現できます。次の宣言を試してみてください。コンマで区切られたすべての値が文字列リストで取得されます。

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}')}")
スティーブン・

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を使用しない場合、フィールドに値を挿入するときにカンマ区切りの文字列を文字列配列にしか取得できませんが、DefaultConversionServiceはいくつかの便利なマジックを実行し、コレクションや配列などに追加します(必要に応じて実装を確認してください)それについてもっと知りたい

これら2つを使用すると、改行を含むすべての冗長な空白も処理できるため、それらをトリミングするために追加のロジックを追加する必要はありません。


この構成の追加は機能していますが、奇妙なことが起こります。ファイルタイプに@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;

2

整数のリストの私の場合、これはうまくいきます:

@Value("#{${my.list.of.integers}}")
private List<Integer> listOfIntegers;

プロパティファイル:

my.list.of.integers={100,200,300,400,999}

または@Value( "#{$ {my.set.of.integers}}")private Set <Integer> setOfIntegers;
Alexey Simonov

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

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

うまくいきます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.