Spring Boot:使用 @Value 或 @ConfigurationProperties 从 yaml 读取列表

Posted

技术标签:

【中文标题】Spring Boot:使用 @Value 或 @ConfigurationProperties 从 yaml 读取列表【英文标题】:Spring Boot: read list from yaml using @Value or @ConfigurationProperties 【发布时间】:2016-01-26 23:26:26 【问题描述】:

我想从 yaml 文件 (application.yml) 中读取主机列表,该文件如下所示:

cors:
    hosts:
        allow: 
            - http://foo1/
            - http://foo2/
            - http://foo3/

(示例 1)

我使用的类定义了这样的值:

@Value("$cors.hosts.allow")   
List<String> allowedHosts;

但由于 Spring 抱怨,读取失败:

java.lang.IllegalArgumentException:无法解析占位符 字符串值“$cors.hosts.allow”中的“cors.hosts.allow”

当我像这样更改文件时,可以读取属性,但它自然不包含列表,而只有一个条目:

cors:
    hosts:
        allow: http://foo1, http://foo2, http://foo3

(我知道我可以将这些值读取为一行并将它们按"," 拆分,但我还不想寻求解决方法)

这也不起作用(尽管我认为根据snakeyamls docs这应该是有效的):

cors:
    hosts:
        allow: !!seq [ "http://foo1", "http://foo2" ] 

(跳过!!seq 而只使用[ / ] 也是失败的)

我阅读了 here 的建议,其中涉及使用 @ConfigurationProperties 并将示例转移到 Java 并与您在示例 1 中看到的 yaml 文件一起使用:

@Configuration
@EnableWebMvc
@ConfigurationProperties(prefix = "cors.hosts")
public class CorsConfiguration extends WebMvcConfigurerAdapter 
    @NotNull
    public List<String> allow;
...

当我运行此程序时,我会收到以下投诉:

org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 1 错误字段“允许”上的对象“cors.hosts”中的字段错误:被拒绝 值[空];代码 [NotNull.cors.hosts.allow,NotNull.allow,NotNull]; 论据 [org.springframework.context.support.DefaultMessageSourceResolvable: 代码 [cors.hosts.allow,allow];参数 ts [];默认消息 [允许]];

我搜索了其他方法来配置我的 CORS 主机,并找到了这个 Spring Boot issue,但由于这还没有完成,我不能将它用作解决方案。 所有这些都是通过 Spring Boot 1.3 RC1 完成的

【问题讨论】:

似乎是一个未解决的 Spring 错误 (SPR-11759)。 @BohuslavBurghardt 我试图切换到@ConfigurationProperties,不幸的是这也不起作用。 【参考方案1】:

我已经能够从下面的属性中读取列表-

属性-

cors.hosts.allow[0]=host-0
cors.hosts.allow[1]=host-1

读取属性-

@ConfigurationProperties("cors.hosts")
public class ReadProperties 
    private List<String> allow;

    public List<String> getAllow() 
       return allow;
    
    public void setAllow(List<String> allow) 
        this.allow = allow;
    

【讨论】:

逗号分隔值适用于 yaml。所以它应该是:主机:允许:habuma-20,habuma-21 我会赞成这个。这可能不适合这个问题,但我偶然发现了这个答案,这正是我想要的。【参考方案2】:

很简单,答案就在这个doc 和this one

所以,你有一个这样的 yaml:

cors:
    hosts:
        allow: 
            - http://foo1/
            - http://foo2/
            - http://foo3/

那你先绑定数据

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@ConfigurationProperties(prefix="cors.hosts")
public class AllowedHosts 
    private List<String> HostNames; //You can also bind more type-safe objects

然后在另一个组件中你只是这样做

@Autowired
private AllowedHosts allowedHosts;

你就完成了!

【讨论】:

为我工作!但是我必须将我的类创建为静态类,否则我得到 beaninstantiationexception 说它缺少默认构造。 只是一个简单的更改 - 您需要一个 getter,以便您可以在具有 AllowedHosts 的 Autowired 实例的组件中访问 allowedHost。【参考方案3】:

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

corsHostsAllow: http://foo1/, http://foo2/, http://foo3/

用于访问的java代码

@Value("$corsHostsAllow")    
String[] corsHostsAllow

我试过了,成功了;)

【讨论】:

它也适用于列表:'@Value("$realtime.tokenPermissions") private List tokenPermissions;' 它对我不起作用! ... ir 不会将它刚刚加载的值拆分为单值列表 你也可以使用 List。并且没有@Value(字段名就足够了)【参考方案4】:

我遇到了同样的问题,但是解决了,给你我的解决方案

exclude-url: >
  /management/logout,
  /management/user/login,
  /partner/logout,
  /partner/user/login

Spring boot 2.1.6.RELEASE版本成功

【讨论】:

我猜这更像是一个分割成多行的字符串,而不是一个列表

以上是关于Spring Boot:使用 @Value 或 @ConfigurationProperties 从 yaml 读取列表的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot- Spring Boot特性2

在Spring-boot中,为@Value注解添加从数据库读取properties支持

Spring Boot 程序化日志配置

spring boot @ConfigurationProperties vs @Value

spring boot @Value 获取计算机中绝对路径文件的内容

spring boot 项目属性配置