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.