Özellikler dosyasından bir listeyi okuma ve yay ek açıklaması ile yükleme @Value


244

Yani .properties dosyasında değerlerin bir listesini istiyorum, yani:

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

Ve doğrudan sınıfımda yüklemek için, yani:

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

Anladığım kadarıyla, bunu yapmanın bir alternatifi, spring config dosyasına sahip olmak ve bir fasulye referansı olarak yüklemek (yanlışsam beni düzelt), yani

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

Ama bunu yapmanın bir yolu var mı? .properties dosyası mı kullanıyorsunuz? ps: Bunu mümkünse herhangi bir özel kod ile yapmak istiyorum.

Yanıtlar:


454

Spring EL Kullanımı:

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

Özellikler dosyanızın aşağıdakilerle doğru yüklendiğini varsayarsak:

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

1
Kullandığınız aynı sürümü kullanarak tekrar kontrol ettim. Spring EL'i aynen yazıdaki gibi kopyaladı ve çalışıyor. Farklı olan, eğer EL'imde bir hata yaparsam, bir org.springframework.expression.spel.SpelEvaluationExceptionistisna alıyorum javax.el.ELException. İtirazınız Spring tarafından mı oluşturuldu?
Wilhelm Kleu

1
Bahar 3.2 ile mükemmel çalışır.
ehsanullahjan

17
Boş mülk nasıl my.list.of.strings=? Burada böyle bir öğe (boş dize) olacak boş liste yeniden bu tür işlevsellik beklerdim, değil mi?
Jan Zyka

5
Ayrıca önerilen çözümün kırpma yapmadığını unutmayın, bu nedenle gibi değerler item1, item2, item3size gerçekten beklemediğiniz sonuçları verebilir (ipucu: boşluklar).
Jan Zyka

4
Boş alanları kırpmak gerekirse bölünmüş argüman için regex kullanın .. gibi bir şey@Value("#{'${my.list.of.strings}'.split(',\\s*')}")
Stackee007

88

İlkbahar 3.0'dan bu yana,

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

için senin applicationContext.xml(veya şeyler yapılandırmak yerde). Dmitry Chornyi'nin bir yorumda belirttiği gibi, Java tabanlı yapılandırma şöyle görünüyor:

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

Bu String, Collectiontürlere dönüştürmeyi destekleyen yeni yapılandırma hizmetini etkinleştirir . Bu yapılandırma hizmetini etkinleştirmezseniz, Spring bu tür dönüştürmeyi desteklemeyen yapılandırma özellikleri olarak eski özellik düzenleyicilerine geri döner.

Diğer tür koleksiyonlara da dönüştürme çalışmaları:

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

gibi bir çizgi ile çalışacak

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

Oradaki boşlukla ilgili hiçbir sorun yok ConversionServiceFactoryBean, bununla ilgileniyor.

Bkz. Http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#core-convert-Spring-config

Bir Spring uygulamasında, her Spring kapsayıcısı (veya ApplicationContext) başına bir ConversionService örneği yapılandırırsınız. Bu ConversionService, Spring tarafından alınır ve daha sonra çerçeve tarafından bir tür dönüştürmenin gerçekleştirilmesi gerektiğinde kullanılır. [...] Spring'e hiçbir ConversionService kayıtlı değilse, orijinal PropertyEditor tabanlı sistem kullanılır.


6
Java yapılandırması: @Bean public ConversionService conversionService () {return new DefaultConversionService (); }
Dmitry Chornyi

2
split()Her ifadede kendinizi tekrar etmekten kaçınmak dışında , size vermek yerine boş bir listeyi de düzgün bir şekilde işler[null]
Didier L

Mülkün geçersiz kılınması durumunda çalışmaz (Birden fazla mülk kaynağında bulunur.)
Daniel Hári

47

Bunu okuyorsanız ve Spring Boot kullanıyorsanız , bu özellik için 1 seçeneğiniz daha var

Genellikle virgülle ayrılmış liste gerçek dünya kullanım durumu için çok sakar (Ve bazen yapılandırmanızda virgül kullanmak istiyorsanız, hatta mümkün değil):

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

İle Bahar Boot , (İndeks 0'dan başlamalı) bu gibi yazabilirsiniz:

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

Ve şu şekilde kullanın:

@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

Burada açıklanan diğer çözümlerin tanınan beeing değil kaçan virgüller nedeniyle çalışmadığı bir sorun var. Bu çözümü Spring 4 ile yapmanın bir yolu var mı?
sandrozbinden

34

my.list.of.strings=ABC,CDE,EFGİn .properties dosyasını belirterek ve kullanarak

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

Dizelerin dizilerini alabilirsiniz. Ve kullanarak CollectionUtils.addAll(myList, myString), dizelerin listesini alabilirsiniz.


Ben sadece ilk String "ABC" alıyorum
Osama Abdulsattar

19

Yapıcıyı mı @Autowiredyoksa bir pasajı String.split()mı ve vücutta ing'i düşündün mü ?

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

Kodumun test edilebilirliğini artırmak için bu yollardan birini kullanarak otomatik kablolama yapmayı tercih ederim.


14

Spring Boot 2 kullanıyorsanız, herhangi bir ek yapılandırma olmadan olduğu gibi çalışır.

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

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

benim için çalışmadı, yukarıda gösterildiği gibi Bahar EL'i kullanmak zorundayım.
Bilbo Baggins

hattaprivate List<String> myList;
Halayem Anis

Evet benim için de çalıştı: Spring Boot 2.2.6 kullanıyorum
Ankit

8

Yukarıdaki tüm cevaplar doğrudur. Ancak bunu tek bir satırda başarabilirsiniz. Lütfen bildirimi izlemeyi deneyin ve tüm Dize listesinde virgülle ayrılmış tüm değerleri alırsınız.

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

Ayrıca, xml yapılandırmanızda aşağıdaki satırın tanımlanmış olması gerekir.

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

özellikler dosyanızın yolunu ve dosya adını değiştirmeniz yeterlidir. Ve gitmekte fayda var. :)

Umarım bu size yardımcı olur. Şerefe.


1
Bu benim için işe yaradı, ama bu açıklamaları şöyle ifade etmek zorunda kaldım:@Value("#{T(java.util.Arrays).asList('${my.list.of.strings}')}")
Steven

6

En son Spring framework sürümünü kullanıyorsanız (Spring 3.1+, inanıyorum), SpringEL'de bu dize bölünmüş şeylere ihtiyacınız yok,

Baharınızın Yapılandırma sınıfına (Yapılandırma ile açıklamalı olan) PropertySourcesPlaceholderConfigurer ve DefaultConversionService öğelerini eklemeniz yeterlidir.

@Configuration
public class AppConfiguration {

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

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

ve sınıfında

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

ve özellikler dosyasında

list=A,B,C,D,E

DefaultConversionService olmadan, virgülle ayrılmış String'i String dizisine yalnızca alanınıza değer enjekte ettiğinizde alabilirsiniz, ancak DefaultConversionService sizin için birkaç uygun sihir yapar ve bunları Koleksiyona, Diziye vb. hakkında daha fazla bilgi edinmek ister)

Bu ikisi ile, newline dahil olmak üzere tüm gereksiz beyaz boşlukları bile işler, bu yüzden onları kırpmak için ek mantık eklemenize gerek yoktur.


Bu yapılandırmanın eklenmesi çalışıyor ancak garip bir şey oluyor: Dosya türü için @Value kullanamıyorum, Dosyayı Kaynak ile değiştirmeliyim.
ad3luc

2

bunu böyle ek açıklamalarla yapabilirsiniz

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

burada my.list.of.strings özellikler dosyasından seçilecek, eğer orada değilse, a, b, c varsayılanları kullanılacak

ve özellikler dosyanızda böyle bir şeye sahip olabilirsiniz

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


2

Değerlerdeki boşluklara dikkat edin. Yanlış olabilirim, ama virgülle ayrılmış listedeki boşlukların @Value ve Spel kullanılarak kesilmediğini düşünüyorum. Liste

foobar=a, b, c

dizelerin bir listesi olarak okunur

"a", " b", " c"

Çoğu durumda boşlukları istemezsiniz!

İfade

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

size dizelerin bir listesini verir:

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

Normal ifade, virgülden hemen önce ve hemen sonra tüm boşlukları kaldırır. Değerlerin içindeki boşluklar kaldırılmaz. Yani

foobar = AA, B B, CCC

değerlerle sonuçlanmalıdır

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

Senin örneğin basitleştirilmiş böylece split () yöntemi kullanır içten, sınırlayıcı olarak regex: <br/>@Value("#{'${foobar}'.trim().split( *, *)}")
Karlik_B

2

Bu dizi kapma ve sıyırma boşlukları için daha basit olduğunu düşünüyorum:

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

2

Tamsayıların bir listesi durumunda bu çalışır:

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

Özellik dosyası:

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

veya @Value ("# {$ {my.set.of.integers}}") özel Set <Integer> setOfIntegers;
Alexey Simonov

1

Commons Configuration'ı kullanmayı düşünün. Özellikler dosyasındaki bir girişi diziye / listeye bölmek için yerleşik bir özelliğe sahiptir. SpEL ve @Value ile tarama yapmak istediğiniz şeyi vermelidir


İstendiği gibi, ihtiyacınız olan şey (Gerçekten kodu denemedim, bazı yazım hataları olabilir, lütfen benimle ayı):

Apache Commons Yapılandırmasında PropertiesConfiguration var. Sınırlandırılmış dizeyi dizi / listeye dönüştürme özelliğini destekler.

Örneğin, bir özellikler dosyanız varsa

#Foo.properties
foo=bar1, bar2, bar3

Aşağıdaki kod ile:

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

size bir dize dizisi verecektir ["bar1", "bar2", "bar3"]

Spring ile kullanmak için, bunu uygulama bağlamınızda xml'de bulundurun:

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

ve bunu bahar fasulyenize koyun:

public class SomeBean {

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

Bunun çalışması gerektiğine inanıyorum: P


kullanılacak yöntem ve sınıf hakkında daha spesifik olabilir ve gerçek örnek kod sniplet harika olurdu.
JackDev

1

Tercih ettiğim yol (özellikle dizeler için) aşağıdakilerdir:

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

ve kullan

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

Bu şekilde, parametrenize virgül de ekleyebilirsiniz. Setler için de çalışır.


0

eğer mülk yer tutucuları kullanılıyorsa ser1702544 örneği

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

Yer tutucu xml ile:

<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 kullanıyorum

Mülk dosyam:

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

Kodum:

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

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

İyi çalışıyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.