Konfiguracja Spring Boot yaml dla listy ciągów

149

Próbuję załadować tablicę ciągów z pliku application.yml. To jest konfiguracja:

ignore:
    filenames:
        - .DS_Store
        - .hg

To jest klasa:

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

Istnieją inne konfiguracje w tej samej klasie, które ładują się dobrze. W moim pliku yaml nie ma żadnych zakładek. Nadal mam następujący wyjątek:

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

Odpowiedzi:

71

Moje przypuszczenie to, że @Valuenie radzi sobie z „kompleks” typów. Możesz wybrać taką klasę rekwizytów:

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

Uwaga: ten kod to Groovy - a nie Java - żeby przykład był krótki! Zobacz komentarze, aby uzyskać wskazówki, jak adoptować.

Zobacz pełny przykład https://github.com/christoph-frick/so-springboot-yaml-string-list

cfrick
źródło
1
Możesz powiązać przecinki oddzielone przecinkami @Value(o ile zarejestrowany jest konwerter, który, jak sądzę, będzie w Spring Boot).
Dave Syer
2
Odbiera
1
Nie mogłem go zmusić do pracy @Configuration, ale użycie @Componentzamiast tego załatwiło sprawę .
Stijn Van Bael
1
@cfrick tak, to była jedyna zmiana, jaką wprowadziłem. Patrząc na cel obu adnotacji, powiedziałbym, że @Componentjest bardziej odpowiedni: stackoverflow.com/questions/12229282/ ...
Stijn Van Bael
2
To jak wygląda to z ograniczeniem procesów startowych wiosna że adnotacja - github.com/spring-projects/spring-boot/issues/501
wontondon
133

użyj wartości oddzielonych przecinkami w application.yml

ignoreFilenames: .DS_Store, .hg

kod java umożliwiający dostęp

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

To działa ;)

Ahmet Vehbi Olgaç
źródło
Miałem nadzieję, że to zadziała również w Dropwizard: `` (dzięki!
RST
1
To powinna być najlepsza odpowiedź.
Mohamed Elsayed,
3
W moich własnych testach jest to równoważne z „.DS_Store, .hg”, ale nie „.DS_Store”, „.hg” - ten ostatni kończy się niepowodzeniem z „org.yaml.snakeyaml.parser.ParserException: podczas parsowania mapowania bloków”. Więc to, co robisz tutaj, to dostarczanie właściwości jako pojedynczego ciągu oddzielonego przecinkami (który Spring następnie dzieli na tablicę lub listę) zamiast tablicy YAML. To „działa”, ale nie odpowiada na pierwotne pytanie. Jeszcze nie znalazłem sposobu na przeanalizowanie tablicy YAML we właściwości fasoli z adnotacjami @Value.
Zirzirikos
38

Z dokumentacji rozruchowej wiosennej https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Listy YAML są reprezentowane jako klucze właściwości z wyłuskiwaniem [indeksu], na przykład ten YAML:

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

Zostałyby przekształcone w te właściwości:

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

Aby powiązać z właściwościami takimi jak ta za pomocą narzędzi Spring DataBinder (co jest tym, co @ConfigurationPropertiesrobi), musisz mieć właściwość w docelowym komponencie bean typu java.util.Listi musisz albo podać setter, albo zainicjować go zmienną wartością, np. To będzie wiązać do właściwości powyżej. Oto jak wyglądałby kod pytania.

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

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

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}
dskow
źródło
2
To powinno działać, BTW getXxx()jest konieczne, aby działało i musi używać a Listnie Set.
Eric Wang
W yaml lista wartości dla ArrayList może być listą rozdzielaną przecinkami. W moim przypadku mam wiele wartości, więc lista kompaktowa jest czystsza niż pozycja w wierszu. Więc w przykładzie możesz zrobić serwery: dev.bar.com, foo.bar.com
Violaman
25

Oprócz odpowiedzi Ahmeta możesz dodać znaki końca linii do ciągu oddzielonego przecinkami za pomocą >symbolu.

application.yml :

ignoreFilenames: >
  .DS_Store, 
  .hg

Kod Java :

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;
Sasha Shpota
źródło
Działa to dobrze, o ile nie ma więcej przecinków (,) w łańcuchach.
Valentin Despa
To nie działa, aby czytać właściwości jako arraylista. Czyta je jako pojedynczy ciąg.
Sree Lakshmi
6

Odpowiedź Ahmeta wyjaśnia, jak przypisać wartości oddzielone przecinkami do tablicy String.

Aby użyć powyższej konfiguracji w różnych klasach, może być konieczne utworzenie do tego metod pobierających / ustawiających. Ale jeśli chciałbyś załadować tę konfigurację raz i nadal używać jej jako elementu bean z adnotacją Autowired, oto jak osiągnąłem:

W ConfigProvider.java

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

Na zajęciach zewnętrznych:

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

możesz używać tej samej listy wszędzie indziej, korzystając z automatycznego okablowania.

Deepak
źródło
To działa. W moim przypadku jednak aplikacja nie powiodła się, chyba że dodam @Configurationna początku zajęć w ConfigProvider.java. W przeciwnym razie źródło wymagało komponentu bean typu „java.util.List”, którego nie można znaleźć.
Diana
3
@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

yml plik:

your:
 elements: element1, element2, element3

Dzięki Spring SpEL możesz grać o wiele więcej.

Vivek Swansi
źródło
2

Cóż, jedyne, co mogę zrobić, to tak:

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

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

I nie zapomnij o @Configuration nad twoją klasą ....

Bez separacji „,” nie ma takiego szczęścia ...

Działa też (wersja boot 1.5.8)

servers: 
       dev.example.com,
       another.example.com
Roland Roos
źródło
-1

W moim przypadku był to problem ze składnią w pliku .yml. Miałem:

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

a lista w moim pliku .yml:

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

nie czyta w polu z adnotacją @ Wartość. Kiedy zmieniłem składnię w pliku .yml na:

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

działało dobrze.

Matt Campbell
źródło
Próbując tego na spring-boot 1.5 to nie działa. Potrzebujesz dwukropka po bootstrap-
serverach
-2
@Value("${your.elements}")    
private String[] elements;

yml plik:

your:
 elements: element1, element2, element3
sashanet buryk
źródło
1
Czym różni się ta od odpowiedzi Ahmeta? stackoverflow.com/a/41462567/2065796
Sasha Shpota
1
Odpowiedź już udzielona. Odpowiadanie tylko ze względu na punkty nie dodaje wartości
Deepak,