Настройка Spring Boot yaml для списка строк

149

Я пытаюсь загрузить массив строк из файла application.yml. Это конфиг:

ignore:
    filenames:
        - .DS_Store
        - .hg

Это класс:

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

В том же классе есть другие конфигурации, которые загружаются просто отлично. В моем файле yaml нет вкладок. Тем не менее я получаю следующее исключение:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'ignore.filenames' in string value "${ignore.filenames}"
Бахадыр Яган
источник

Ответы:

71

Я думаю , что @Valueне может справиться со «сложными» типами. Вы можете пойти с классом опоры как это:

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

Пожалуйста , обратите внимание: Этот код Groovy - не Java - сохранить пример короче! Смотрите комментарии для советов, как принять.

Смотрите полный пример https://github.com/christoph-frick/so-springboot-yaml-string-list

cfrick
источник
1
Вы можете связать их через запятую @Value(до тех пор, пока зарегистрирован конвертер, который будет в Spring Boot, я думаю).
Дейв Сайер
2
Он подбирает настройки строки, но не настройки списка <String>
Bahadır Yağan
1
Я не мог заставить его работать @Configuration, но @Componentвместо этого добился цели.
Стейн Ван Баел
1
@cfrick да, это было единственное изменение, которое я сделал. Глядя на назначение обеих аннотаций, я бы сказал, что @Componentэто более уместно: stackoverflow.com/questions/12229282/…
Stijn Van Bael
2
Похоже, что это ограничение для процессов весенней загрузки, аннотация - github.com/spring-projects/spring-boot/issues/501
wontondon
134

используйте разделенные запятыми значения в application.yml

ignoreFilenames: .DS_Store, .hg

Java-код для доступа

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

Это работает ;)

Ахмет Вехби Ольгач
источник
Я надеялся, что это сработает и в Dropwizard: '(хотя, спасибо!
RST
1
Это должен был быть лучший ответ.
Мохаммед Эльзайед
3
В моих собственных тестах это эквивалентно ".DS_Store, .hg", но не ".DS_Store", ".hg" - последний завершается ошибкой с "org.yaml.snakeyaml.parser.ParserException: при разборе сопоставления блоков". Итак, что вы на самом деле делаете, так это предоставляете свойство в виде отдельной строки, разделенной запятыми (которую Spring затем разделяет на массив или список) вместо массива YAML. Это «работает», но не отвечает на первоначальный вопрос. Мне еще предстоит найти способ анализа массива YAML в аннотированном свойстве компонента @Value.
Zirzirikos
38

Из весенних загрузочных документов https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Списки YAML представлены в виде ключей свойств с разыменованием [index], например, это YAML:

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

Будет преобразован в эти свойства:

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

Для привязки к таким свойствам с помощью утилит Spring DataBinder (что и @ConfigurationPropertiesделает) вам нужно иметь свойство в целевом bean-компоненте типа java.util.Listи вам нужно либо предоставить установщик, либо инициализировать его изменяемым значением, например, это будет связывать к свойствам выше. Вот как будет выглядеть код вопроса.

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

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

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}
dskow
источник
2
Это должно работать, BTW getXxx()необходим для работы, и должен использовать, а Listне Set.
Эрик Ван
В yaml список значений для ArrayList может быть списком с разделителями-запятыми. В моем случае у меня много значений, поэтому компактный список чище, чем элемент в строке. Так что в примере вы можете сделать серверы: dev.bar.com, foo.bar.com
Violaman
Может ли YAML быть загружен из файла свойств , как это: servers: ${my.servers}? Чтобы попасть my.servers[0]и my.servers[1]в Ямл? Я пытаюсь иметь сценически зависимые конфигурации
ochs.tobi
25

В дополнение к ответу Ахмета вы можете добавить разрывы строк к строке, разделенной запятой, используя >символ.

application.yml :

ignoreFilenames: >
  .DS_Store, 
  .hg

Java-код :

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;
Саша Шпота
источник
Это работает хорошо, если у вас больше нет запятых (,) в ваших строках.
Валентин Деспа
Это не работает для чтения свойств как arraylist. Он читает их как одну строку.
Шри Лакшми
6

Ответ Ахмета дает представление о том, как присваивать значения через запятую массиву String.

Чтобы использовать указанную выше конфигурацию в разных классах, вам может потребоваться создать для нее геттеры / сеттеры. Но если вы хотите загрузить эту конфигурацию один раз и продолжать использовать ее как компонент с аннотацией Autowired, вот как я это сделал:

В ConfigProvider.java

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

На внешних занятиях:

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

Вы можете использовать тот же список в любом месте, используя автопроводку.

Дипак
источник
Это работает. В моем случае, хотя приложение не удалось, если я не добавлю @Configurationв начале класса в ConfigProvider.java. В противном случае я получил источник требуется bean-компонент типа «java.util.List», который не может быть найден.
Диана
3
@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

YML-файл:

your:
 elements: element1, element2, element3

С пружинным SPEL можно играть намного больше.

Вивек Суонси
источник
2

Ну, единственное, что я могу заставить это работать, это так:

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

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

И не забудьте @Configuration над вашим классом ....

Без "," разделения, нет такой удачи ...

Тоже работает (загрузочная версия 1.5.8)

servers: 
       dev.example.com,
       another.example.com
Роланд Роос
источник
-1

В моем случае это была проблема с синтаксисом в файле .yml. Я имел:

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

и список в моем файле .yml:

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

не читал в аннотированное поле @ Value. Когда я изменил синтаксис в файле .yml:

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

это работало нормально.

Мэтт Кэмпбелл
источник
Попытка этого на Spring-boot 1.5 это не работает. Тебе нужно двоеточие после начальной загрузки серверов
Taugenichts
-2
@Value("${your.elements}")    
private String[] elements;

YML-файл:

your:
 elements: element1, element2, element3
сашанет бурык
источник
1
Как это отличается от ответа Ахмета? stackoverflow.com/a/41462567/2065796
Саша Шпота
1
Ответ уже предоставлен. Ответ только ради очков не добавляет ценности
Дипак