2017-08-31 51 views
0

我在本文结尾处提供了一种解决方案,但是执行此操作的首选方法是什么?我的用例是跨多个配置文件读取yaml,并合并到映射到java类的单个配置中。跨越多个弹簧配置文件合并yaml

描述这个问题的样例项目在https://github.com/balamuru/yaml-pojo-merge

如。请看下面的POJO

public class Credentials { 
    private String user; 
    private String password; 
} 

这可以被组合成一个集合多种方式

凭据对象的集合凭证 直接描述实例在默认对象

public class AllCredentials { 
    private List<Credentials> credentials; //won't merge (will override instead) because spring doesn't know which original Credential list item to over-ride when an override value is supplied in the profile (for instance , if only one password is supplied, spring doesn't know whether to update list item 1 or 2 etc) 
} 
public class FamilyCredentials { 
    private Credentials husband; //the corresponding yaml is determinate - and spring can determine exactly what field to update 
    private Credentials wife; 
} 

相应的表示和配置文件特定的YML文件如下

com.foo.bar.allcreds: 
    credentials: 
    - user: bill 
     password: bi123 
    - user: hilary 
     password: h123 

com.foo.bar.famcreds: 
    husband: 
    user: bill 
    password: bi123 
    wife: 
    user: hilary 
    password: h123 

--- 
spring.profiles: prod 
com.foo.bar.allcreds: 
    credentials: 
    - password: [email protected] 
    - password: [email protected] 

com.foo.bar.famcreds: 
    husband: 
    password: [email protected] 
    wife: 
    password: [email protected]  

观察到,在List的情况下,Spring不能确定哪个凭证实例更新密码(即使用户名是supplicied),因为它提供了一个项目列表,并且不能保证所有项目都是提供,或(甚至为此事)

OTOH,FamilyCredentials YAML解决完美,因为密码字段的路径格式正确和确定。

如果处理无限数据结构,解决方案是使用一些东西,使我们能够限定被修改的段,即hashmap。这是一个可以工作的数据结构(关键字“mr_prez”和“first_lady”可以精确解析更新的合格yaml属性)。

本项目中的测试案例证明了这一点。

public class AllCredentialsMap { 
    private Map<String, Credentials> credentials; 
and the corresponding yaml segments 

com.foo.bar.allcredsmap: 
    credentials: 
    mr_prez: 
     user: bill 
     password: bi123 
    first_lady: 
     user: hilary 
     password: h123 

--- 
spring.profiles: prod 

com.foo.bar.allcredsmap: 
    credentials: 
    mr_prez: 
     password: [email protected] 
    first_lady: 
     password: [email protected] 

回答

0

我厌倦了你的项目,请参阅下列变化:

配置元数据的关键,如果它发现在积极配置文件相同的密钥,但你必须遵循相同的列表模式(com.foo.bar.allcreds)将得到重写:

com.foo.bar.allcreds: 
    credentials: 
    - user: bill 
     password: [email protected] 
    - user: hilary 
     password: [email protected] 


@Configuration 
@EnableConfigurationProperties 
@ConfigurationProperties(prefix = "com.foo.bar.allcreds") 
public class AllCredentials { 
    private List<Credentials> credentials; 

    public List<Credentials> getCredentials() { 
     return credentials; 
    } 

    public void setCredentials(List<Credentials> credentials) { 
     this.credentials = credentials; 
    } 

} 


public class Credentials { 

    private String user; 
    private String password; 

} 

application.yml:

com.foo.bar.allcreds: 
    credentials: 
    - user: bill 
     password: [email protected] 
    - user: hilary 
     password: [email protected] 

测试:

@RunWith(SpringRunner.class) 
@SpringBootTest 
@ActiveProfiles("prod") 
public class YamlPojoMergeApplicationTests { 



    @Autowired 
    AllCredentials allCredentials; 



    //This works 
    @Test(expected = AssertionError.class) 
    public void testAllCredentials() { 
     Credentials credentials1 = allCredentials.getCredentials().get(0); 
     Credentials credentials2 = allCredentials.getCredentials().get(1); 

     assertThat(credentials1.getUser(), is(equalTo("bill"))); 
     assertThat(credentials1.getPassword(), is(equalTo("[email protected]"))); 

     assertThat(credentials2.getUser(), is(equalTo("hilary"))); 
     assertThat(credentials2.getPassword(), is(equalTo("[email protected]"))); 
    } 

} 

上合并一些有用的讨论(不建议使用),你可以在这里找到它:

https://github.com/spring-projects/spring-boot/issues/2750