web-dev-qa-db-fra.com

Lecture d'une liste à partir d'un fichier de propriétés et chargement avec l'annotation printanière @Value

Semblable à cette question: http://forum.springsource.org/showthread.php?111992-Loading-a-list-from-properties-file-using-Value-annotation (pour lequel il n'y a pas de réponse)

Je veux avoir une liste de valeurs dans un fichier .properties, par exemple:

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

Et pour le charger directement dans ma classe, à savoir:

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

Si j'ai bien compris, vous pouvez le faire dans le fichier de configuration printanier et le charger comme référence de bean (corrigez-moi si je me trompe), c'est-à-dire

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

Mais y a-t-il un moyen de le faire? Vous utilisez un fichier .properties? ps: Je voudrais le faire sans code personnalisé si possible.

171
JackDev

Utilisation de Spring EL:

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

En supposant que votre fichier de propriétés est chargé correctement avec les éléments suivants:

my.list.of.strings=ABC,CDE,EFG
344
Wilhelm Kleu

Depuis le printemps 3.0, vous pouvez ajouter une ligne comme

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

à votre applicationContext.xml (ou à l'endroit où vous configurez les choses) .. Comme Dmitry Chornyi le souligne dans un commentaire, la configuration basée sur Java ressemble à ceci:

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

Cela active le nouveau service de configuration qui prend en charge la conversion de String en Collection types . Si vous n'activez pas ce service de configuration, Spring utilise ses éditeurs de propriétés hérités en tant que services de configuration qui ne prennent pas en charge ce type de conversion.

La conversion en collections d’autres types fonctionne également:

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

travaillera avec une ligne comme

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

Aucun problème d’espace, la ConversionServiceFactoryBean en prend soin.

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

Dans une application Spring, vous configurez généralement une instance ConversionService par conteneur Spring (ou ApplicationContext). Ce service de conversion sera récupéré par Spring, puis utilisé chaque fois qu'une conversion de type doit être effectuée par la structure . [...] Si aucun service de conversion n'est enregistré auprès de Spring, le système d'origine PropertyEditor est utilisé.

74

En spécifiant le my.list.of.strings=ABC,CDE,EFG dans le fichier .properties et en utilisant 

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

Vous pouvez obtenir les tableaux de chaînes. Et en utilisant CollectionUtils.addAll(myList, myString), vous pouvez obtenir la liste des chaînes.

28
Crazy Developer

Avez-vous envisagé @Autowireding le constructeur ou un setter et String.split()ing dans le corps?

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

J'ai tendance à préférer effectuer l'auto-recrutement d'une de ces manières pour améliorer la testabilité de mon code.

18
nicholas.hauschild

Si vous lisez ceci et que vous utilisez Spring Boot , vous avez 1 option supplémentaire pour cette fonctionnalité

Généralement, les listes séparées par des virgules sont très maladroites dans le cas d'utilisation réel (Et parfois même impossible, si vous voulez utiliser des virgules dans votre configuration):

[email protected],[email protected],[email protected],.....

Avec Spring Boot , vous pouvez l’écrire de la manière suivante (l’index commence à 0):

email.sendTo[0][email protected]
email.sendTo[1][email protected]
email.sendTo[2][email protected]

Et utilisez-le comme ceci:

@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
16
Ng Sek Long

Toutes les réponses ci-dessus sont correctes. Mais vous pouvez y parvenir en une seule ligne . Essayez la déclaration suivante et vous obtiendrez toutes les valeurs séparées par des virgules dans une liste de chaînes.

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

Et vous devez également définir la ligne suivante dans votre configuration XML.

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

remplacez simplement le chemin et le nom de votre fichier de propriétés. Et vous êtes prêt à partir. :)

J'espère que cela vous aide. À votre santé.

7
Japan Trivedi

Si vous utilisez la dernière version du framework Spring (Spring 3.1+, je crois), vous n'avez pas besoin de ces fonctions de scission de chaîne dans SpringEL,

Ajoutez simplement PropertySourcesPlaceholderConfigurer et DefaultConversionService dans la classe Configuration de votre ressort (celle avec la configuration annotée avec Configuration), par exemple, 

@Configuration
public class AppConfiguration {

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

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

et dans ta classe 

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

et dans le fichier de propriétés

list=A,B,C,D,E

Sans DefaultConversionService, vous ne pouvez utiliser une chaîne séparée dans une matrice que lorsque vous injectez la valeur dans votre champ, mais DefaultConversionService effectue quelques opérations magiques pratiques et les ajoutera à Collection, Array, etc. (vérifiez l'implémentation aime en savoir plus à ce sujet)

Avec ces deux logiciels, il gère même tous les espaces blancs redondants, y compris newline. Vous n'avez donc pas besoin d'ajouter de logique pour les découper.

2
wonhee

vous pouvez le faire avec des annotations comme celle-ci

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

ici my.list.of.strings sera choisi dans le fichier de propriétés, s'il n'est pas présent, les valeurs par défaut a, b, c seront utilisées

et dans votre fichier de propriétés, vous pouvez avoir quelque chose comme ça

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

2
verma

Si vous utilisez Spring Boot 2, cela fonctionne tel quel, sans configuration supplémentaire.

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

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

Pensez à utiliser la configuration commune. Il a une fonctionnalité intégrée pour casser une entrée dans un fichier de propriétés en tableau/liste. Combiner avec SpEL et @Value devrait donner ce que vous voulez


Comme demandé, voici ce dont vous avez besoin (Je n'ai pas vraiment essayé le code, vous avez peut-être quelques typo, merci de le supporter avec moi):

Dans Apache Commons Configuration, il y a PropertiesConfiguration. Il prend en charge la fonctionnalité de conversion de chaîne délimitée en tableau/liste.

Par exemple, si vous avez un fichier de propriétés

#Foo.properties
foo=bar1, bar2, bar3

Avec le code ci-dessous:

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

vous donnera un tableau de chaînes de ["bar1", "bar2", "bar3"]

Pour utiliser avec Spring, insérez ceci dans le contexte de votre application xml:

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

et avoir ceci dans votre haricot de printemps:

public class SomeBean {

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

Je crois que cela devrait fonctionner: P

1
Adrian Shum

Attention aux espaces dans les valeurs. Je peux me tromper, mais je pense que les espaces de la liste séparée par des virgules ne sont pas tronqués avec @Value et Spel. La liste

foobar=a, b, c

serait lu comme une liste de chaînes

"a", " b", " c"

Dans la plupart des cas, vous ne voudriez probablement pas les espaces!

L'expression

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

vous donnerait une liste de chaînes:

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

L'expression régulière supprime tous les espaces juste avant et juste après une virgule. Les espaces à l'intérieur des valeurs ne sont pas supprimés. Alors

foobar = AA, B B, CCC

devrait aboutir à des valeurs

"AA", "B B", "CCC".
1
DAMungra

Je pense que ceci est plus simple pour récupérer le tableau et supprimer des espaces:

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

si vous utilisez des espaces réservés de propriété, ser1702544 par exemple deviendrait 

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

Avec espace réservé 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
cgull