Spring Boot Yaml-Konfiguration für eine Liste von Zeichenfolgen

149

Ich versuche, ein Array von Zeichenfolgen aus der Datei application.yml zu laden. Dies ist die Konfiguration:

ignore:
    filenames:
        - .DS_Store
        - .hg

Das ist die Klasse:

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

Es gibt andere Konfigurationen in derselben Klasse, die einwandfrei geladen werden. In meiner Yaml-Datei befinden sich keine Registerkarten. Trotzdem bekomme ich folgende Ausnahme:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'ignore.filenames' in string value "${ignore.filenames}"
Bahadır Yağan
quelle

Antworten:

71

Meine Vermutung ist, dass die @Value"komplexen" Typen nicht bewältigen können. Sie können mit einer Requisitenklasse wie dieser gehen:

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

Bitte beachten Sie: Dieser Code ist Groovy - nicht Java - um das Beispiel kurz zu halten! In den Kommentaren finden Sie Tipps zur Übernahme.

Siehe das vollständige Beispiel https://github.com/christoph-frick/so-springboot-yaml-string-list

cfrick
quelle
1
Sie können ein durch Kommas getrenntes mit binden @Value(solange ein Konverter registriert ist, was meiner Meinung nach in Spring Boot sein wird).
Dave Syer
2
Es nimmt String-Einstellungen auf, aber nicht List <String> -Einstellungen
Bahadır Yağan
1
Ich konnte es nicht zum Laufen bringen @Configuration, aber @Componentstattdessen war es der Trick.
Stijn Van Bael
1
@cfrick ja es war die einzige Änderung, die ich vorgenommen habe. Wenn ich den Zweck beider Anmerkungen betrachte, würde ich sagen @Component, dass dies angemessener ist: stackoverflow.com/questions/12229282/…
Stijn Van Bael
2
Dies
scheint
133

Verwenden Sie in application.yml durch Kommas getrennte Werte

ignoreFilenames: .DS_Store, .hg

Java-Code für den Zugriff

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

Es funktioniert ;)

Ahmet Vehbi Olgaç
quelle
Ich hatte gehofft, dass dies auch in Dropwizard funktionieren würde: '(danke!
RST
1
Das hätte die beste Antwort sein sollen.
Mohamed Elsayed
3
In meinen eigenen Tests entspricht dies ".DS_Store, .hg", aber nicht ".DS_Store", ".hg" - letzteres schlägt mit "org.yaml.snakeyaml.parser.ParserException: beim Parsen einer Blockzuordnung" fehl. Was Sie hier also tatsächlich tun, ist die Bereitstellung der Eigenschaft als einzelne durch Kommas getrennte Zeichenfolge (die Spring dann in ein Array oder eine Liste aufteilt) anstelle eines YAML-Arrays. Dies "funktioniert", beantwortet aber nicht die ursprüngliche Frage. Ich habe noch keine Möglichkeit gefunden, ein YAML-Array in einer mit @Value kommentierten Bean-Eigenschaft zu analysieren.
Zirzirikos
38

Aus den Spring Boot-Dokumenten https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

YAML-Listen werden als Eigenschaftsschlüssel mit [Index] -Deferenzern dargestellt, z. B. diese YAML:

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

Würde in diese Eigenschaften umgewandelt werden:

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

Um mit den Spring DataBinder-Dienstprogrammen an solche Eigenschaften zu binden (was auch immer der @ConfigurationPropertiesFall ist), müssen Sie eine Eigenschaft in der Ziel-Bean des Typs haben java.util.Listund entweder einen Setter bereitstellen oder sie mit einem veränderlichen Wert initialisieren, z. B. wird dies binden zu den Eigenschaften oben. So würde der Code der Frage aussehen.

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

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

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}
dskow
quelle
2
Dies sollte funktionieren, BTW getXxx()ist notwendig, damit es funktioniert, und muss ein verwenden List, nicht Set.
Eric Wang
In der yaml kann die Liste der Werte für die ArrayList eine durch Kommas getrennte Liste sein. In meinem Fall habe ich viele Werte, sodass eine kompakte Liste sauberer ist als ein Element pro Zeile. Im Beispiel können Sie also Server erstellen: dev.bar.com, foo.bar.com
Violaman
25

Zusätzlich zu Ahmets Antwort können Sie der durch Koma getrennten Zeichenfolge mithilfe eines >Symbols Zeilenumbrüche hinzufügen .

application.yml :

ignoreFilenames: >
  .DS_Store, 
  .hg

Java-Code :

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;
Sasha Shpota
quelle
Dies funktioniert gut, solange Sie keine Kommas (,) mehr in Ihren Zeichenfolgen haben.
Valentin Despa
Dies funktioniert nicht, um Eigenschaften als Arrayliste zu lesen. Es liest sie als einzelne Zeichenfolge.
Sree Lakshmi
6

Ahmets Antwort enthält Informationen zum Zuweisen der durch Kommas getrennten Werte zum String-Array.

Um die obige Konfiguration in verschiedenen Klassen zu verwenden, müssen Sie möglicherweise Getter / Setter dafür erstellen. Wenn Sie diese Konfiguration jedoch einmal laden und diese weiterhin als Bean mit Autowired-Annotation verwenden möchten, habe ich Folgendes erreicht:

In ConfigProvider.java

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

In externen Klassen:

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

Sie können dieselbe Liste überall sonst verwenden, indem Sie automatisch verdrahten.

Deepak
quelle
Das funktioniert. In meinem Fall ist die Anwendung jedoch fehlgeschlagen, es sei denn, ich füge @Configurationzu Beginn der Klasse in hinzu ConfigProvider.java. Ansonsten habe ich für Source eine Bean vom Typ 'java.util.List' benötigt, die nicht gefunden werden konnte.
Diana
3
@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

yml-Datei:

your:
 elements: element1, element2, element3

Es gibt noch viel mehr, was Sie mit Spring Spel spielen können.

Vivek Swansi
quelle
2

Nun, das einzige, was ich zum Laufen bringen kann, ist wie folgt:

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

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

Und vergessen Sie nicht die @ Konfiguration über Ihrer Klasse ...

Ohne die "," Trennung kein solches Glück ...

Funktioniert auch (Boot 1.5.8 Versie)

servers: 
       dev.example.com,
       another.example.com
Roland Roos
quelle
-1

In meinem Fall war dies ein Syntaxproblem in der .yml-Datei. Ich hatte:

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

und die Liste in meiner .yml-Datei:

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

hat nicht in das mit @ Value annotierte Feld gelesen. Als ich die Syntax in der .yml-Datei geändert habe in:

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

es hat gut funktioniert.

Matt Campbell
quelle
Wenn Sie dies mit Spring-Boot 1.5 versuchen, funktioniert dies nicht. Sie benötigen einen Doppelpunkt nach Bootstrap-Servern
Taugenichts
-2
@Value("${your.elements}")    
private String[] elements;

yml-Datei:

your:
 elements: element1, element2, element3
Sashanet Buryk
quelle
1
Wie ist diese andere Form Ahmets Antwort? stackoverflow.com/a/41462567/2065796
Sasha Shpota
1
Antwort bereits gegeben. Nur um der Punkte willen zu antworten, bringt keinen Mehrwert
Deepak