Загрузка нескольких файлов YAML (с использованием @ConfigurationProperties?)

Использование Spring Boot 1.3.0.RELEASE

У меня есть пара файлов yaml, описывающих несколько экземпляров программы. Теперь я хочу разобрать все эти файлы в List<Program> (карту, что угодно), чтобы позже я мог искать наиболее подходящий экземпляр для заданных критериев во всех программах.

Мне очень нравится подход с @ConfigurationProperties, и он достаточно хорошо работает для одного yaml-файла, но я еще не нашел способа прочитать все файлы в каталоге, используя этот метод.

Текущий подход работает для одного файла:

programs/program1.yml

name: Program 1
minDays: 4
maxDays: 6

можно прочитать

@Configuration
@ConfigurationProperties(locations = "classpath:programs/program1.yml", ignoreUnknownFields = false)
public class ProgramProperties {

private Program test; //Program is a POJO with all the fields in the yml.
//getters+setters

Я попытался изменить местоположения на массив, в котором перечислены все мои файлы locations = {"classpath:programs/program1.yml", "classpath:programs/program2.yml"}, а также использовать locations = "classpath:programs/*.yml", но это по-прежнему загружает только первый файл (массив-подход) или вообще ничего (подстановочный знак).

Итак, мой вопрос: как лучше всего в Spring Boot загрузить кучу файлов yaml в каталог пути к классам и проанализировать их в (список) POJO, чтобы их можно было автоматически связать в контроллере? Нужно ли мне использовать Snakeyaml напрямую, или есть встроенный механизм, который я еще не нашел?

РЕДАКТИРОВАТЬ: рабочий подход делает это вручную:

    private static final Yaml yaml = new Yaml(new Constructor(Program.class));
private static final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

try {
        for (Resource resource : resolver.getResources("/programs/*.yml")) {

            Object data = yaml.load(resource.getInputStream());

            programList.add((Program) data);
        }
    }
    catch (IOException ioe) {
        logger.error("failed to load resource", ioe);
    }

person Alex    schedule 03.12.2015    source источник
comment
Подстановочный знак не будет работать AFAIK, но использование массива должно работать, однако вы, похоже, забыли в нем префикс classpath:.   -  person M. Deinum    schedule 03.12.2015
comment
спасибо за вклад, я отредактировал свой текст выше - так как он, естественно, был в моем коде при попытке. Однако, если этот подход ДОЛЖЕН работать, как мне написать свой класс (или изменить yaml-структуру?), чтобы Программа не просто заполнялась данными из первого yaml-файла, а становилась списком всех разные программы?   -  person Alex    schedule 03.12.2015


Ответы (2)


В Spring можно загрузить несколько файлов свойств конфигурации, используя аннотацию PropertySource, но не файлы YAML. См. раздел 26.6.4 по ссылке ниже:

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties

Однако из вашей проблемы кажется, что вы можете настроить все свои программы в одном YAML, а затем получить весь список программ в одном списке.

Образец YAML (all.yaml)

programs:
  - name: A
    min: 1
    max: 2
  - name: B
    min: 3
    max: 4

Конфиг.java

@Configuration
@ConfigurationProperties(locations={"classpath:all.yaml"})
public class Config{

    private List<Program> programs;

    public void setPrograms(List<Program> programs) {
        this.programs = programs;
    }

    public List<Program> getPrograms() {
        return programs;
    }
}
person Mohit    schedule 03.12.2015
comment
спасибо mohit, это определенно работает, и это был мой первый подход, но я хотел пойти по пути отдельного файла, так как одна программа может стать довольно большой, и полученный all.yaml будет ужасно поддерживать... - person Alex; 03.12.2015
comment
Что ж, в таком случае вы можете использовать аннотацию @ConfigurationProperties для метода, а затем загрузить конфигурацию, написав свой собственный код. Этот подход больше того, что вы включили в вопрос, с дополнительным преимуществом автоматической проводки списка «Программы». - person Mohit; 04.12.2015
comment
Просто и к вашему сведению: аргумент locations в @ConfigurationProperties был обесценен в 1.4 в пользу настройки среды напрямую с дополнительными местоположениями. - person Peter Kirby; 10.01.2018

То, что я сейчас делаю, насколько я понял ваш вопрос, почти то же самое. У меня есть application.yml, а также файлы yml для конкретного профиля, например. application-{profile}.yml в моем src/main/resources. В application.yml я определил ключевые значения профиля по умолчанию, которые частично переопределяются специфичными для профиля файлами yml.

Если вы хотите иметь безопасный и четко определенный доступ к вашему ключу/значению YML, вы можете использовать следующий подход:

 @ConfigurationProperties
 public class AppSettings {
     String name; // has to be the same as the key in your yml file

     // setters/getters

 }

В вашей конфигурации Spring-Boot вы должны добавить следующие аннотации в свой класс конфигурации:

@ComponentScan
@EnableAutoConfiguration
@EnableConfigurationProperties( value = { AppSettings.class, SomeOtherSettings.class } )
public class SpringContextConfig {

     @Autowired
     private AppSettings appSettings;

     public void test() {
          System.out.println(appSettings.getName());
     }
}

@Autowiring также доступен из других бинов. Наоборот (без дополнительного отдельного и безопасного для типов класса, доступ к YML-значениям осуществляется через @Value("${name}").

Вкратце сведем воедино: Да, можно использовать несколько файлов YAML для вашего приложения через Spring-профили. Вы определяете свой текущий активный профиль Spring с помощью аргументов команды, программно или через системную среду (SPRING_PROFILES_ACTIVE=name1,name2). Поэтому у вас может быть несколько файлов application.yml для каждого профиля (см. выше).

person mchlfchr    schedule 03.12.2015
comment
Я не думаю, что это был вопрос о том, как называть разные файлы профиля application.yml. - person ampofila; 06.09.2020