java:commons-configuration2读取yaml及组合配置定义(CombinedConfiguration)
之前写过一篇博客 《java:commons-configuration2与spring的集成》介绍了如何在Spring下集成commons-configuration2,通过commons-configuration2来管理spring环境的所有配置。当时并没有介绍如何支持yaml格式的配置文件。
Spring本身默认是用application.yaml来提供系统配置定义的。如果commons-configuration2能支持YAML格式,就更方便了。
commons-configuration2其实也提供了对YAML格式文件的原生支持。本文代码示例如何使用commons-configuration2完成对yaml的支持
读取YAML
commons-configuration2本身有一个类org.apache.commons.configuration2.YAMLConfiguration
实现YAML的读写。
如下在resources下定义了application.yaml,内容如图右侧
如下单元测试示例如何使用YAMLConfiguration
来读取指定的YAML文件
/**
* YAML读取测试
*/
@Test
public void test1ReadYamlConfiguration() {
try {
// 加载YAML文件
Parameters params = new Parameters();
URL yamlUrl = getClass().getClassLoader().getResource("application.yaml");
System.out.printf("yamlUrl:%s\n",yamlUrl);
ConfigurationBuilder<YAMLConfiguration> yamlBuilder =
new FileBasedConfigurationBuilder<>(YAMLConfiguration.class)
.configure(params.fileBased()
.setURL(getClass().getResource("/application.yaml")));
YAMLConfiguration config = yamlBuilder.getConfiguration();
/** 返回所有参数名 */
Iterator<String> keys = config.getKeys();
/** 读取指定参数 */
Object url = config.getProperty("datasources.ds0.url");
System.out.printf("keys:%s\n",JSON.toJSONString(keys));
System.out.printf("url:%s\n",url);
} catch (Throwable e) {
e.printStackTrace();
fail();
}
}
组合配置(CombindConfiguration)中支持ymal(一)
在上一节的基础上
如下通过XML文件定义了组合多个配置文件组成的组合配置,
definition.xml
<configuration>
<header>
<providers>
<provider config-tag="yaml"
config-class="net.facelib.cell.config.YAMLConfigurationBuilderProvider"/>
</providers>
</header>
<additional>
<xml fileName="defaultConfig.xml"/>
<yaml fileName="application.yaml" config-optional="true" config-name="builtinYaml"/>
</additional>
</configuration>
组合配置中定义了两个配置文件,其中<yam/>
标签指定了YAML格式的配置文件application.yaml。这个yaml标签不是commons-configuration2内置的标签,是我定义的标签
关于commons-configuration2内置的标签参见官方文档《Configuration definition file reference》
如下单元测试代码介绍如何在让commons-configuration2识别自定义的<yam/>
标签并正确读取application.yaml
中的值
/**
* 手工指定解析YAML的 {@link ConfigurationBuilderProvider}实例
*/
@Test
public void test2CombinedWithYAML() {
try {
/** 用于解析YAML的{@link ConfigurationBuilderProvider}实例 */
BaseConfigurationBuilderProvider provider = new BaseConfigurationBuilderProvider(
/* normal builder */
FileBasedConfigurationBuilder.class.getName(),
/* reloading builder */
ReloadingFileBasedConfigurationBuilder.class.getName(),
/* configuration class */
YAMLConfiguration.class.getName(),
/* Parameters; here we assume that we have a custom parameters class
derived from FileBasedBuilderParametersImpl */
Collections.singleton(FileBasedBuilderParametersImpl.class.getName()));
URL definitionlUrl = getClass().getClassLoader().getResource("definition.xml");
System.out.printf("definitionlUrl:%s\n",definitionlUrl);
Configurations configs = new Configurations();
configs.getParameters().combined().registerProvider("yaml", provider);
CombinedConfigurationBuilder builder = new CombinedConfigurationBuilder().configure(
configs.getParameters().fileBased().setURL(definitionlUrl),
/** 手工指定解析yaml的 ConfigurationBuilderProvider实例 */
configs.getParameters().combined().registerProvider("yaml", provider));
CombinedConfiguration config = builder.getConfiguration();
Iterator<String> keys = config.getKeys();
Object url = config.getProperty("datasources.ds0.url");
System.out.printf("keys:%s\n",JSON.toJSONString(keys));
System.out.printf("url:%s\n",url);
} catch (Throwable e) {
e.printStackTrace();
fail();
}
}
组合配置(CombindConfiguration)中支持ymal(二)
上面的代码还可以更简化一些
将上面代码中创建的BaseConfigurationBuilderProvider实例,实现为一个类
YAMLConfigurationBuilderProvider.java
import java.util.Collections;
import org.apache.commons.configuration2.YAMLConfiguration;
import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.combined.BaseConfigurationBuilderProvider;
public class YAMLConfigurationBuilderProvider extends BaseConfigurationBuilderProvider{
public YAMLConfigurationBuilderProvider() {
super(
/* normal builder */
FileBasedConfigurationBuilder.class.getName(),
/* reloading builder */
ReloadingFileBasedConfigurationBuilder.class.getName(),
/* configuration class */
YAMLConfiguration.class.getName(),
/* Parameters; here we assume that we have a custom parameters class
derived from FileBasedBuilderParametersImpl */
Collections.singleton(FileBasedBuilderParametersImpl.class.getName()));
}
}
如下在组合配置定义中通过<provider></provider>
指定解析<yaml/>
标签的类为上面定义的YAMLConfigurationBuilderProvider
。
definitionWithProvider.xml
<configuration>
<header>
<providers>
<provider config-tag="yaml"
config-class="your.package.YAMLConfigurationBuilderProvider"/>
</providers>
</header>
<additional>
<xml fileName="defaultConfig.xml"/>
<yaml fileName="application.yaml" config-optional="true" config-name="builtinYaml"/>
</additional>
</configuration>
然后上面的单元测试代码就可以简化为:
/**
* 用于解析YAML的{@link ConfigurationBuilderProvider}类定义在definitionWithProvider.xml中
*/
@Test
public void test3CombinedWithYAMLInProviderXml() {
try {
URL definitionlUrl = getClass().getClassLoader().getResource("definitionWithProvider.xml");
System.out.printf("definitionlUrl:%s\n",definitionlUrl);
Configurations configs = new Configurations();
CombinedConfiguration config = configs.combined(definitionlUrl);
Iterator<String> keys = config.getKeys();
Object url = config.getProperty("datasources.ds0.url");
System.out.printf("keys:%s\n",JSON.toJSONString(keys));
System.out.printf("url:%s\n",url);
} catch (Throwable e) {
e.printStackTrace();
fail();
}
}
参考资料
《Combining Configuration Sources》
《Configuration definition file reference》
《Extending the configuration definition file format》
《BasicConfigurationBuilder》