如何引用java.util.Properties中的另一个属性?
Java属性文件可以引用其他属性文件吗?
## define a default directory for Input files dir.default=/home/data/in/ dir.proj1=${dir.default}p1 dir.proj2=${dir.default}p2 dir.proj3=${dir.default}p3
这可能吗?
这是你想要的,有点旧了,但可能会满足你的需求。
在属性值中启用常量replace
您可以在属性值的任何位置replace一个常量,并且在一个值内甚至可以有多个常量,如下例所示:
CONST_1 = shoes and ships CONST_2 = sealing wax SomeValue = {CONST_1} and {CONST_2}
在这个例子中,“SomeValue”属性评估为“鞋和船舶和封蜡”。
Eproperties是一个开源项目 ,它提供了variablesreplace以及其他一些特性 – 尽pipereplace可能是最有用的。 它是java.util.Properties的一个子类,可以被任何其他可以将configuration信息作为Properties的类使用。
标准属性文件只是键值对。 在文本格式中, Properties
只是将键与值分开,并执行一些简单的操作,例如允许转义字符。 您可以使用详细的XML语法来定义实体。
如果你想要自己的replace语法,那么你可以像处理任何其他string一样操纵返回的值。 或者,您可以编写自己的版本的Properties
或生成文件时进行replace。
Commons Config lib也可以这样做。 http://commons.apache.org/configuration/userguide/overview.html#Using_Configuration
不过,正如已经指出的那样,看看EProperties库吧; http://code.google.com/p/eproperties/
它支持许多整洁的特性(如replace,嵌套,列表),包括包含,扩展Java属性,比Commons Config(它也允许你使用include语法包含属性)轻了一些。
java.util.Properties类不会为你做这个。 子类的属性不会太困难,重写load()方法并自己进行replace。
由于eproperties是有点不维护和commonsconfiguration依赖于日志logging(具有讽刺意味的是你不能用它来configuration日志logging)我使用这个代码片段,只需要commons-lang(3)
加载插值的属性:
@SuppressWarnings("serial") public static Map<String,String> loadPropertiesMap(InputStream s) throws IOException { final Map<String, String> ordered = new LinkedHashMap<String, String>(); //Hack to use properties class to parse but our map for preserved order Properties bp = new Properties() { @Override public synchronized Object put(Object key, Object value) { ordered.put((String)key, (String)value); return super.put(key, value); } }; bp.load(s); final Map<String,String> resolved = new LinkedHashMap<String, String>(ordered.size()); StrSubstitutor sub = new StrSubstitutor(new StrLookup<String>() { @Override public String lookup(String key) { String value = resolved.get(key); if (value == null) return System.getProperty(key); return value; } }); for (String k : ordered.keySet()) { String value = sub.replace(ordered.get(k)); resolved.put(k, value); } return resolved; }
input :
blah=${user.dir} one=1 two=2 five=5 fifteen=${one}${five} twoonefive=${two}${fifteen} six=6
输出 :
blah=/current/working/dir one=1 two=2 five=5 fifteen=15 twoonefive=215 six=6
很明显Map<String,String>
如果你需要的话Map<String,String>
你可以将Map<String,String>
转换回一个Properties
对象。 我根据先前声明的属性和系统属性来parsing,但是您可以明显地在StrSubstitutor.lookup
调整它。
在这种特殊情况下(以及其他情况),您最好通过定义不同的属性来解决重复问题:
- 将
dir.proj1=dir.default /p1
更改为dir.proj1_extension=/p1
- prepend:
dir.default
到dir.proj1_extension
以获取应用程序代码中proj1的完整位置。
为其他项目做同样的事情。
下面是Java中的代码片段,用于读取引用其他属性的属性。 具体来说,这些是可重用的查询,但也可以是其他的东西。
LinkedHashMap<String, String> sqlsRaw = loadPropertiesFromFile(); LinkedHashMap<String, String> sqls = new LinkedHashMap<>(); StrSubstitutor substitutor = new StrSubstitutor(sqls); for (Map.Entry<String, String> entry : sqlsRaw.entrySet()) { String sql = entry.getValue(); try { sql = substitutor.replace(sql); } catch (Exception e) { throw new RuntimeException("Found an sql with a non replaced reference to another. Please validate that the required key was defined before this sql: " + entry.getValue(), e); } sqls.put(entry.getKey(), sql); }
示例属性:
key1=value1 key21=value2 ${key1}
运行这个之后, key21
的值是value2 value1
。
*使用Apache的StrSubstitutor
。