【问题标题】:Spring Boot yaml configuration for a list of strings字符串列表的 Spring Boot yaml 配置
【发布时间】:2014-12-29 05:34:31
【问题描述】:

我正在尝试从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}"

【问题讨论】:

    标签: spring-boot


    【解决方案1】:

    在 application.yml 中使用逗号分隔值

    ignoreFilenames: .DS_Store, .hg
    

    用于访问的java代码

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

    它正在工作;)

    【讨论】:

    • 我希望这也能在 Dropwizard 中工作 :'( 不过谢谢!
    • 在我自己的测试中,这等价于 ".DS_Store, .hg" 但不是 ".DS_Store", ".hg" - 后者因 "org.yaml.snakeyaml.parser.ParserException 而失败: 在解析块映射时”。因此,您实际上在这里所做的是将属性提供为单个逗号分隔的字符串(Spring 然后将其拆分为数组或列表)而不是 YAML 数组。这“有效”但不回答原始问题。我还没有找到一种方法来解析 @Value 注释 bean 属性中的 YAML 数组。
    【解决方案2】:

    我的猜测是,@Value 无法处理“复杂”类型。您可以使用这样的道具类:

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

    请注意:此代码是 Groovy - 不是 Java - 保持示例简短!有关如何采用的提示,请参阅 cmets。

    查看完整示例https://github.com/christoph-frick/so-springboot-yaml-string-list

    【讨论】:

    • 你可以绑定一个逗号分隔的@Value(只要注册了转换器,我想它会在Spring Boot中)。
    • @Bahadır 我在这里尝试了这段代码,它可以工作。 @ComponentScan 和朋友们接了这个?
    • 它正在拾取字符串设置,但不是 List 设置
    • 还必须为该属性定义一个getter。
    • 这看起来像是注释的 Spring Boot 进程的限制 - github.com/spring-projects/spring-boot/issues/501
    【解决方案3】:

    来自 Spring Boot 文档 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 类型的属性,并且您需要提供一个 setter,或者初始化它具有可变值,例如这将绑定到上面的属性。这是问题代码的样子。

    @ConfigurationProperties(prefix="ignore")
    public class Filenames {
    
        private List<String> ignoredFilenames = new ArrayList<String>();
    
        public List<String> getFilenames() {
            return this.ignoredFilenames;
        }
    }
    

    【讨论】:

    • 这应该可以工作,顺便说一句,getXxx() 是它工作所必需的,并且必须使用List,而不是Set
    • 在 yaml 中,ArrayList 的值列表可以是逗号分隔的列表。就我而言,我有很多值,所以一个紧凑的列表比每行一个项目更干净。所以在例子中,你可以做服务器:dev.bar.com, foo.bar.com
    • 可以从这样的属性文件中加载 yaml:servers: ${my.servers}?要将my.servers[0]my.servers[1] 放入yaml?我正在尝试使用阶段相关配置
    【解决方案4】:

    除了Ahmet's answer,您还可以使用&gt; 符号为逗号分隔的字符串添加换行符。

    application.yml

    ignoreFilenames: >
      .DS_Store, 
      .hg
    

    Java 代码

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

    【讨论】:

    • 只要您的字符串中没有逗号 (,) 就可以正常工作。
    • 这不能将属性读取为数组列表。它将它们读取为单个字符串。
    【解决方案5】:

    Ahmet's answer 提供了如何将逗号分隔的值分配给字符串数组。

    要在不同的类中使用上述配置,您可能需要为此创建 getter/setter.. 但是,如果您想加载此配置一次并继续将其用作带有 Autowired 注释的 bean,这就是我的完成方式:

    在 ConfigProvider.java 中

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

    在课外:

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

    您可以通过自动装配在其他任何地方使用相同的列表。

    【讨论】:

    • 那行得通。就我而言,尽管应用程序失败了,除非我在 ConfigProvider.java 的类开头添加 @Configuration。否则我得到 Source 需要一个找不到的“java.util.List”类型的 bean。
    【解决方案6】:

    好吧,我唯一能让它工作的就是这样:

    servers: >
        dev.example.com,
        another.example.com
    
    @Value("${servers}")
    private String[] array;
    

    别忘了你班级上方的@Configuration....

    没有“,”分隔,就没有这样的运气......

    也可以(启动 1.5.8 版本)

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

    【讨论】:

    • 不过,我更喜欢第一个带有 > 的版本。如果您放置注释(例如,在每一行之后)IDE(IntelliJ)不会在第一种情况下突出显示注释,但在第二种情况下突出显示它。似乎支持将评论放在第二种情况下,但事实并非如此。如果有注释,解析器在这两种情况下都会失败(spring-boot 2.2.10)。
    【解决方案7】:
    @Value("#{'${your.elements}'.split(',')}")  
    private Set<String> stringSet;
    

    yml 文件:

    your:
     elements: element1, element2, element3
    

    您可以使用 spring spEL 玩更多。

    【讨论】:

      【解决方案8】:

      在我的情况下,这是 .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-annotated 字段。当我将 .yml 文件中的语法更改为:

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

      效果很好。

      【讨论】:

      • 在 spring-boot 1.5 上尝试这个不起作用。 bootstrap-servers 后面需要一个冒号
      【解决方案9】:
      @Value("${your.elements}")    
      private String[] elements;
      

      yml 文件:

      your:
       elements: element1, element2, element3
      

      【讨论】:

      猜你喜欢
      • 2022-11-10
      • 2016-01-17
      • 1970-01-01
      • 2019-10-15
      • 1970-01-01
      • 2015-05-31
      • 1970-01-01
      • 2021-06-10
      • 1970-01-01
      相关资源
      最近更新 更多