Konfigurasi yaml Spring Boot untuk daftar string

149

Saya mencoba memuat array string dari file application.yml. Ini adalah konfigurasi:

ignore:
    filenames:
        - .DS_Store
        - .hg

Ini kelasnya:

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

Ada konfigurasi lain di kelas yang sama yang memuat dengan baik. Tidak ada tab di file yaml saya. Masih saya mendapatkan pengecualian berikut:

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

Jawaban:

71

Dugaan saya adalah, bahwa @Valuetidak dapat mengatasi jenis "kompleks". Anda bisa menggunakan kelas prop seperti ini:

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

Harap dicatat: Kode ini Groovy - bukan Java - untuk membuat contoh singkat! Lihat komentar untuk tips bagaimana mengadopsi.

Lihat contoh lengkap https://github.com/christoph-frick/so-springboot-yaml-string-list

cfrick
sumber
1
Anda dapat mengikat koma-terpisah dengan @Value(selama konverter terdaftar, yang akan di Spring Boot kurasa).
Dave Syer
2
Ini mengambil pengaturan string tetapi tidak
Mendaftar
1
Saya tidak bisa membuatnya bekerja @Configuration, tetapi menggunakan @Componentbukan melakukan trik.
Stijn Van Bael
1
@cfrick ya itu satu-satunya perubahan yang saya buat. Melihat tujuan kedua penjelasan, saya akan mengatakan @Componentlebih tepat: stackoverflow.com/questions/12229282/…
Stijn Van Bael
2
Sepertinya ini adalah batasan dengan proses boot musim semi yang anotasi - github.com/spring-projects/spring-boot/issues/501
wontondon
134

gunakan nilai yang dipisahkan koma di application.yml

ignoreFilenames: .DS_Store, .hg

kode java untuk akses

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

Ini bekerja ;)

Ahmet Vehbi Olgaç
sumber
Saya berharap ini akan bekerja di Dropwizard juga: '(terima kasih!
RST
1
Itu seharusnya menjadi jawaban terbaik.
Mohamed Elsayed
3
Dalam pengujian saya sendiri, ini setara dengan ".DS_Store, .hg" tetapi tidak ".DS_Store", ".hg" - yang terakhir gagal dengan "org.yaml.snakeyaml.parser.ParserException: saat menguraikan pemetaan blok". Jadi apa yang sebenarnya Anda lakukan di sini adalah menyediakan properti sebagai string yang dipisahkan oleh koma (yang Spring kemudian pisahkan menjadi array atau daftar) alih-alih array YAML. Ini "berhasil" tetapi tidak menjawab pertanyaan awal. Saya belum menemukan cara untuk mem-parse array YAML di properti bean beranotasi @Value.
Zirzirikos
38

Dari spring boot docs https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Daftar YAML direpresentasikan sebagai kunci properti dengan [index] dereferencers, misalnya YAML ini:

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

Akan diubah menjadi properti ini:

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

Untuk mengikat properti seperti itu menggunakan utilitas Spring DataBinder (yang berfungsi apa @ConfigurationProperties), Anda perlu memiliki properti di kacang tipe target java.util.Listdan Anda perlu menyediakan setter, atau menginisialisasi dengan nilai yang bisa berubah, misalnya ini akan mengikat ke properti di atas. Di sini akan terlihat seperti apa kode pertanyaan itu.

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

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

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}
dskow
sumber
2
Ini harus berfungsi, BTW getXxx()diperlukan agar bisa berfungsi, dan harus menggunakan List, bukan Set.
Eric Wang
Di yaml, daftar nilai untuk ArrayList bisa berupa daftar yang dibatasi koma. Dalam kasus saya, saya memiliki banyak nilai, jadi daftar ringkas lebih bersih daripada item per baris. Jadi dalam contoh, Anda dapat melakukan server: dev.bar.com, foo.bar.com
Violaman
Bisakah yaml dimuat dari file properti seperti ini servers: ${my.servers}:? Untuk masuk my.servers[0]dan my.servers[1]masuk ke ubi jalar? Saya mencoba untuk memiliki konfigurasi panggung tergantung
ochs.tobi
25

Selain jawaban Ahmet, Anda dapat menambahkan jeda baris ke string yang dipisahkan koma menggunakan >simbol.

application.yml :

ignoreFilenames: >
  .DS_Store, 
  .hg

Kode Java :

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;
Sasha Shpota
sumber
Ini berfungsi dengan baik selama Anda tidak memiliki koma lagi (,) di string Anda.
Valentin Despa
Ini tidak berfungsi untuk membaca properti sebagai daftar array. Bunyinya sebagai String tunggal.
Sree Lakshmi
6

Jawaban Ahmet memberikan cara menetapkan nilai yang dipisahkan koma ke array String.

Untuk menggunakan konfigurasi di atas dalam kelas yang berbeda, Anda mungkin perlu membuat getter / setter untuk ini .. Tetapi jika Anda ingin memuat konfigurasi ini sekali dan terus menggunakan ini sebagai kacang dengan anotasi Autowired, berikut adalah cara yang saya lakukan:

Di ConfigProvider.java

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

Di kelas luar:

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

Anda dapat menggunakan daftar yang sama di mana pun dengan autowiring.

Deepak
sumber
Itu bekerja. Dalam kasus saya meskipun aplikasi gagal, kecuali saya tambahkan @Configurationdi awal kelas ConfigProvider.java. Kalau tidak, saya mendapatkan Sumber diperlukan kacang jenis 'java.util.List' yang tidak dapat ditemukan.
Diana
3
@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

file yml:

your:
 elements: element1, element2, element3

Ada banyak lagi yang bisa kamu mainkan dengan spring spEL.

Vivek Swansi
sumber
2

Ya, satu-satunya hal yang bisa saya lakukan adalah:

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

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

Dan jangan lupa konfigurasi @ di atas kelas Anda ....

Tanpa pemisahan ",", tidak ada keberuntungan seperti itu ...

Bekerja juga (boot 1.5.8 versie)

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

Dalam kasus saya ini adalah masalah sintaksis dalam file .yml. Saya punya:

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

dan daftar di file .yml saya:

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

tidak membaca bidang isian @ Nilai. Ketika saya mengubah sintaks dalam file .yml ke:

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

itu bekerja dengan baik.

Matt Campbell
sumber
Mencoba ini pada spring-boot 1.5 ini tidak berhasil. Anda memerlukan titik dua setelah bootstrap-server
Taugenichts
-2
@Value("${your.elements}")    
private String[] elements;

file yml:

your:
 elements: element1, element2, element3
sashanet buryk
sumber
1
Bagaimana ini berbeda dari jawaban Ahmet? stackoverflow.com/a/41462567/2065796
Sasha Shpota
1
Jawaban sudah disediakan. Menjawab hanya demi poin tidak menambah nilai
Deepak