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}"

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


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

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 ;)


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;
    }
}

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;

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.


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.


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

-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.


Próbując tego na spring-boot 1.5 to nie działa. Potrzebujesz dwukropka po bootstrap-
serverach

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.