Configurazione yaml di Spring Boot per un elenco di stringhe


149

Sto cercando di caricare una matrice di stringhe dal file application.yml. Questa è la configurazione:

ignore:
    filenames:
        - .DS_Store
        - .hg

Questa è la classe:

@Value("${ignore.filenames}")
private List<String> igonoredFileNames = new ArrayList<>();

Ci sono altre configurazioni nella stessa classe che si carica bene. Non ci sono schede nel mio file yaml. Ottengo comunque la seguente eccezione:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'ignore.filenames' in string value "${ignore.filenames}"

Risposte:


71

La mia ipotesi è che @Valuenon possono far fronte a tipi "complessi". Puoi andare con una classe prop come questa:

@Component
@ConfigurationProperties('ignore')
class IgnoreSettings {
    List<String> filenames
}

Nota: questo codice è Groovy - non Java - per mantenere l'esempio breve! Vedi i commenti per suggerimenti su come adottare.

Guarda l'esempio completo https://github.com/christoph-frick/so-springboot-yaml-string-list


1
Puoi associare una virgola separata da @Value(fintanto che è registrato un convertitore, che sarà in Spring Boot credo).
Dave Syer,

2
Sta raccogliendo le impostazioni di stringa ma non le impostazioni Elenco <String>
Bahadır Yağan

1
Non riuscivo a farlo funzionare @Configuration, ma usare @Componentinvece ha fatto il trucco.
Stijn Van Bael,

1
@cfrick sì, è stata l'unica modifica che ho apportato. Osservando lo scopo di entrambe le annotazioni, direi che @Componentè più appropriato: stackoverflow.com/questions/12229282/…
Stijn Van Bael,

2
Sembra che sia una limitazione con i processi di avvio a molla che l'annotazione - github.com/spring-projects/spring-boot/issues/501
wontondon,

134

usa valori separati da virgola in application.yml

ignoreFilenames: .DS_Store, .hg

codice java per l'accesso

@Value("${ignoreFilenames}")    
String[] ignoreFilenames

Funziona ;)


Speravo che funzionasse anche in Dropwizard: '(grazie comunque!
RST

1
Quella avrebbe dovuto essere la risposta migliore.
Mohamed Elsayed,

3
Nei miei test, questo equivale a ".DS_Store, .hg" ma non ".DS_Store", ".hg" - quest'ultimo non riesce con "org.yaml.snakeyaml.parser.ParserException: mentre analizza un mapping dei blocchi". Quindi quello che stai effettivamente facendo qui è fornire la proprietà come una singola stringa separata da virgola (che Spring quindi divide in un array o in un elenco) anziché in un array YAML. Questo "funziona" ma non risponde alla domanda originale. Devo ancora trovare un modo per analizzare un array YAML in una proprietà bean annotata @Value.
Zirzirikos,

38

Dai documenti di avvio primaverili https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Gli elenchi YAML sono rappresentati come chiavi di proprietà con i dereferenziatori [indice], ad esempio questo YAML:

my:
   servers:
       - dev.bar.com
       - foo.bar.com

Si trasformerebbe in queste proprietà:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

Per associare a proprietà del genere utilizzando le utility Spring DataBinder (che è ciò che @ConfigurationPropertiesfa) è necessario disporre di una proprietà nel bean di destinazione di tipo java.util.Liste è necessario fornire un setter o inizializzarlo con un valore modificabile, ad es. alle proprietà sopra. Ecco come sarebbe il codice della domanda.

@ConfigurationProperties(prefix="ignore")
public class Filenames {

    private List<String> ignoredFilenames = new ArrayList<String>();

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}

2
Questo dovrebbe funzionare, BTW getXxx()è necessario perché funzioni, e deve usare un List, no Set.
Eric Wang,

In yaml, l'elenco di valori per ArrayList può essere un elenco delimitato da virgole. Nel mio caso, ho molti valori, quindi un elenco compatto è più pulito di un articolo per riga. Quindi, nell'esempio, puoi fare server: dev.bar.com, foo.bar.com
Violaman

Potrebbe la yaml essere caricato da un file delle proprietà in questo modo: servers: ${my.servers}? Per entrare my.servers[0]e my.servers[1]entrare nello yaml? Sto cercando di avere configurazioni dipendenti dallo stage
ochs.tobi

25

Oltre alla risposta di Ahmet è possibile aggiungere interruzioni di linea alla stringa separata da coma usando il >simbolo.

application.yml :

ignoreFilenames: >
  .DS_Store, 
  .hg

Codice Java :

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;

Funziona bene purché non ci siano più virgole (,) nelle stringhe.
Valentin Despa,

Questo non funziona per leggere le proprietà come arraylist. Li legge come stringa singola.
Sree Lakshmi,

6

La risposta di Ahmet fornisce come assegnare i valori separati da virgola all'array String.

Per utilizzare la configurazione di cui sopra in diverse classi potrebbe essere necessario creare getter / setter per questo. Ma se desideri caricare questa configurazione una volta e continuare a usarla come un bean con annotazione Autowired, ecco come ho realizzato:

In ConfigProvider.java

@Bean (name = "ignoreFileNames")
@ConfigurationProperties ( prefix = "ignore.filenames" )
public List<String> ignoreFileNames(){
    return new ArrayList<String>();
}

Nelle lezioni esterne:

@Autowired
@Qualifier("ignoreFileNames")
private List<String> ignoreFileNames;

puoi utilizzare lo stesso elenco ovunque tramite autowiring.


Che funzioni. Nel mio caso però l'applicazione non è riuscita, a meno che non aggiunga @Configurationall'inizio della lezione in ConfigProvider.java. In caso contrario, ho ottenuto Source richiesto un bean di tipo 'java.util.List' che non è stato possibile trovare.
Diana,

3
@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

file yml:

your:
 elements: element1, element2, element3

C'è molto di più che puoi giocare con lo spel di primavera.


2

Bene, l'unica cosa che posso far funzionare è così:

servers: >
    dev.example.com,
    another.example.com

@Value("${servers}")
private String[] array;

E non dimenticare la @Configuration sopra la tua classe ....

Senza la separazione ",", nessuna tale fortuna ...

Funziona anche (avvio 1.5.8 versie)

servers: 
       dev.example.com,
       another.example.com

-1

Nel mio caso si è trattato di un problema di sintassi nel file .yml. Avevo:

@Value("${spring.kafka.bootstrap-servers}")
public List<String> BOOTSTRAP_SERVERS_LIST;

e l'elenco nel mio file .yml:

bootstrap-servers:
  - s1.company.com:9092
  - s2.company.com:9092
  - s3.company.com:9092

non stava leggendo nel campo annotato @ Value. Quando ho modificato la sintassi nel file .yml in:

bootstrap-servers >
  s1.company.com:9092
  s2.company.com:9092
  s3.company.com:9092

ha funzionato bene.


Provando questo su Spring-Boot 1.5 non funziona. Hai bisogno di due punti dopo bootstrap-server
Taugenichts,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.