【问题标题】:Loading multiple YAML files (using @ConfigurationProperties?)加载多个 YAML 文件(使用 @ConfigurationProperties?)
【发布时间】:2016-03-07 22:19:26
【问题描述】:

使用 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);
    }

【问题讨论】:

  • 通配符在 AFAIK 中不起作用,但使用数组应该可以,但是您似乎忘记了其中的 classpath: 前缀。
  • 感谢您的输入,我在上面编辑了我的文本 - 因为我在尝试时自然地在我的代码中使用了它。但是,如果这种方法应该有效,我将如何编写我的类(或更改 yaml 结构?)程序不仅填充了第一个 yaml 文件中的数据,而且成为所有不同的程序?

标签: java spring spring-boot snakeyaml


【解决方案1】:

在 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

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

【讨论】:

  • 感谢 mohit,这绝对有效,也是我的第一个方法,但我想使用单独的文件路径,因为单个程序可能会变得非常大,并且生成的“all.yaml”将是维持恐怖......
  • 好吧,在这种情况下,您可以在方法上使用@ConfigurationProperties 注解,然后通过编写自己的代码来加载配置。这种方法更多的是您所包含的内容,并具有自动连接 List 的额外优势。
  • 仅供参考:@ConfigurationProperties 中的 locations 参数在 1.4 中被贬值,“有利于直接使用其他位置配置环境”。
【解决方案2】:

据我了解您的问题,我目前正在做的几乎相同。 我有一个 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 也可以从其他 Bean 访问。 另一种方式(没有额外的分隔和类型安全的类,是通过@Value("${name}") 访问 YML 值。

简单地说: 是的,可以通过 Spring-profiles 为您的应用程序使用多个 YAML 文件。您可以通过命令 args、以编程方式或通过系统环境 (SPRING_PROFILES_ACTIVE=name1,name2) 定义当前的活动弹簧配置文件。 因此,每个配置文件可以有多个 application.yml 文件(见上文)。

【讨论】:

  • 我不认为这是关于如何命名不同的配置文件 application.yml 文件的问题。
猜你喜欢
  • 2019-05-16
  • 1970-01-01
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 2014-01-20
  • 2020-12-07
  • 2017-06-01
相关资源
最近更新 更多