1. 占位符基本使用方式
在 apache commons configuration2 中,占位符(variable interpolation)是一种强大的功能,允许在配置值中引用其他配置属性或外部值。
占位符使用 ${前缀:键名} 的格式,其中:
- 前缀:用于标识使用哪个 lookup 实现来解析值
- 键名:传递给 lookup 实现的查找键
1.1 基本语法
占位符的基本格式为:
${前缀:键名}
例如,在配置文件中:
test.url=${classpath:cell-test.key}
test.runtime=${java:runtime}
1.2 工作原理
当配置系统遇到占位符时,会根据前缀查找对应的 lookup 实现,然后调用其 lookup(string key) 方法获取实际值。
这个过程在 configurationreader 类中可以看到:
public class configurationreader {
public configurationreader() {
// 创建combinedconfiguration
this.combinedconfig = new combinedconfiguration();
// 设置表达式引擎为默认表达式引擎
this.combinedconfig.setexpressionengine(defaultexpressionengine.instance());
// 获取stringlookup对象用于变量插值
interpolatorstringlookup interpolator = stringlookupfactory.instance.interpolatorstringlookup();
// 注册自定义的classpath前缀lookup
interpolator.registerlookup("classpath", classpathlookup.instance);
// 为combinedconfiguration设置变量插值器
this.combinedconfig.setinterpolator(interpolator);
// ...
}
}
2. 默认提供的占位符
apache commons configuration2 通过 defaultlookups 和 defaultstringlookup 提供了多种默认的占位符实现。
2.1 defaultlookups 提供的占位符
defaultlookups 是 apache commons configuration2 中定义的枚举类,提供了各种内置的 lookup 实现:
| 前缀 | 描述 | 使用示例 |
|---|---|---|
| base64decoder | base64 解码 | ${base64decoder:sgvsbg8gv29ybgq=} |
| base64encoder | base64 编码 | ${base64encoder:hello world} |
| const | 常量引用 | ${const:java.io.file.separator} |
| date | 日期格式化 | ${date:yyyy-mm-dd} |
| env | 环境变量 | ${env:path} |
| file | 文件内容 | ${file:/path/to/file.txt} |
| java | java 系统属性 | ${java:runtime} |
| localhost | 本地主机信息 | ${localhost:name} |
| properties | 属性文件 | ${properties:config.properties:key} |
| resourcebundle | 资源绑定 | ${resourcebundle:messages:greeting} |
| script | 脚本执行 | ${script:javascript:1+1} |
| sys | 系统属性(同java) | ${sys:user.home} |
| url | url内容 | ${url:http://example.com} |
| urldecoder | url解码 | ${urldecoder:https%3a%2f%2fexample.com} |
| urlencoder | url编码 | ${urlencoder:https://example.com} |
| xml | xml内容 | ${xml:/path/to/file.xml:/root/child/text()} |
2.2 defaultstringlookup 提供的占位符
defaultstringlookup 是 apache commons text 库中的枚举类,为字符串查找提供了各种实现:
| 键名 | 对应的查找器 | 描述 |
|---|---|---|
| base64decoder | base64decoderstringlookup | base64 解码 |
| base64encoder | base64encoderstringlookup | base64 编码 |
| const | constantstringlookup | java 常量引用 |
| date | datestringlookup | 日期格式化 |
| env | environmentvariablestringlookup | 环境变量 |
| file | filestringlookup | 文件内容读取 |
| java | javaplatformstringlookup | java 平台信息 |
| localhost | localhoststringlookup | 本地主机信息 |
| properties | propertiesstringlookup | 属性文件读取 |
| resourcebundle | resourcebundlestringlookup | 资源绑定 |
| script | scriptstringlookup | 脚本执行 |
| sys | systempropertystringlookup | 系统属性 |
| url | urlstringlookup | url内容读取 |
| urldecoder | urldecoderstringlookup | url解码 |
| urlencoder | urlencoderstringlookup | url编码 |
| xml | xmlstringlookup | xml内容读取 |
3. 自定义占位符实现
3.1 实现 lookup 接口
要创建自定义占位符,需要实现 apache commons configuration2 的 lookup 接口。
以下是 classpathlookup 的实现示例:
public class classpathlookup implements lookup {
public static final classpathlookup instance = new classpathlookup();
@override
public object lookup(string variable) {
if(strings.isnullorempty(variable)) {
return null;
}
url resourceurl = getclass().getclassloader().getresource(variable);
return (resourceurl != null) ? resourceurl : null;
}
}
3.2 注册自定义 lookup
实现 lookup 接口后,需要将其注册到配置系统中。在 configurationreader 类中,可以看到如何注册自定义 lookup:
// 获取stringlookup对象用于变量插值
interpolatorstringlookup interpolator = stringlookupfactory.instance.interpolatorstringlookup();
// 注册自定义的classpath前缀lookup
interpolator.registerlookup("classpath", classpathlookup.instance);
// 为combinedconfiguration设置变量插值器
this.combinedconfig.setinterpolator(interpolator);
3.3 使用自定义占位符
注册后,可以在配置文件中使用自定义占位符。根据 classpathlookuptest 的示例:
# 在cell-config.properties中定义
test.url=${classpath:cell-test.key}
test.url2=${classpath:nofound.key}
test.runtime=${java:runtime}
3.4 测试示例
以下是测试自定义占位符的示例代码:
@test
public void test1classpathlookup() {
// 读取通过classpath前缀定义的资源路径(url)
string value = config.getstring("test.url");
log("value:{}", value);
assertnotnull(value);
assertnotequals("${classpath:cell-test.key}", value); // 验证占位符已被解析
// 读取为url类型
url urlvalue = config.get(url.class, "test.url");
log("value:{}", urlvalue);
assertnotnull(urlvalue);
// 测试不存在的资源(应保留原始占位符)
string notfound = config.getstring("test.url2");
log("value:{}", notfound);
assertequals("${classpath:nofound.key}", notfound); // 资源不存在时保持原样
}
4. 实现细节与注意事项
4.1 占位符解析行为
- 当 lookup 返回
null时,原始占位符字符串会被保留 - 占位符可以嵌套使用
- 默认情况下,占位符使用
${}格式,可以自定义表达式引擎更改格式
4.2 classpathlookup 实现特点
- 使用单例模式(instance 常量)
- 对空输入进行处理,返回 null
- 当资源未找到时返回 null,而不是抛出异常
- 返回 url 对象,而不是路径字符串
4.3 性能考虑
- 频繁使用的 lookup 实现应考虑使用缓存
- 对于资源密集型操作,应确保 lookup 实现高效
5. 总结
apache commons configuration2 的占位符机制提供了灵活强大的配置管理能力:
- 通过
${前缀:键名}格式在配置中引用外部值 - 内置多种 lookup 实现满足常见需求
- 可以通过实现 lookup 接口轻松扩展自定义占位符
classpathlookup展示了如何创建从类路径加载资源的自定义占位符
通过合理使用占位符,可以构建更加灵活、可维护的配置系统,特别是在需要引用外部资源或环境变量的场景中。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
参考资料:
apache commons configuration2 官方文档
apache commons text 官方文档
发表评论