.properties文件是否适合存储分层设置 - 对象?

时间:2014-09-22 08:53:00

标签: java properties-file

我的任务是工作中的任务,需要持久的客户端设置。这些设置由我正在实现的框架的C#版本中的XML文件表示,它表示具有最多六层的层次结构的对象。此外,不同级别中的对象数有时是任意的,如ArrayList。遗憾的是,对象序列化不是一种选择,因为需要能够直接编辑文件。我不得不将这些设置的持久性实现为.properties文件,但我对这是否是一个好主意感到担忧。

据我所知,.properties文件只能以与HashMap相同的方式使用,只有字符串的键值配对。复杂对象的表示似乎只能用长而复杂的关键字符串表示,它代表每个元素的整个“路径”,包括它可能在几个列表中的单个索引。

filters.filter3.traces.rule4.add1.value="8"

我无法找到任何合适的方法来在.properties文件中保留分层对象,但我也无法找到任何明确的证据证明它不可能。

那么,.properties文件是否适合存储分层设置 - 对象?或者我应该将我的属性实现为XML文件还是JSON?

4 个答案:

答案 0 :(得分:1)

我会坚持使用XML文件。没有什么比使用API​​框架的不同变体的不同格式更能激怒用户。

您可以使用Apache XMLBeans等库来简化读取和写入XML文件的过程,使用模式文件自动生成适当的Java类。

属性文件可用于存储分层数据,但手动编辑这些内容真的很痛苦,并且很容易引入错误。有些人认为XML编辑也不是轻而易举,但至少存在编辑器可以在与XSD链接时更容易编辑。

答案 1 :(得分:1)

我总是发现这种存储分层配置数据的方式非常麻烦,但它很有可能。例如,它(曾经是?)是配置Log4j的最常用方式,但根据我的经验,越来越多的开发人员也在这里切换到XML。

我真的没有看到为此目的使用属性文件的重点。

答案 2 :(得分:1)

我认为你已经掌握了它的要点 - Java属性文件可以表达层次结构,但是很笨拙。

查看Typesafe Config library,这是Play Framework使用的内容。它的主要语言是HOCON(人工优化配置符号),它非常适合表达层次结构属性。该库还可以兼容属性文件和JSON,因此您可以轻松地同时支持所有这些语言。

在Java属性文件中,正如您所说,您仅限于使用虚线键

a.b.c = 42

在HOCON中,您可以选择执行此操作或使用花括号嵌套部分。因此,该示例可以通过以下任何方式表达:

a.b.c : 42

a {
    b.c : 42
}

a.b {
    c : 42
}

a {
    b {
        c : 42
    }
}

答案 3 :(得分:1)

您有一个log4j形式的完美示例:此处是来自here的属性示例。

log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File = logs/bensApps.log
log4j.appender.R.Append = true
log4j.appender.R.DatePattern = '.'yyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

如果您在这些键中有层次结构,例如:

Map<String,Object> root = new HashMap<>();
root.put("level1", "foobar");
root.put("level2", Collections.singletonMap("p", "foobar");

您可以将其翻译成:

level1=foobar
level2.p=foobar

在阅读文件时,将.拆分为子图:

Map<String, Object> root = new HashMap<>();
Properties propz = new Properties();
// load from your file
for (Map.Entry<String,Object> entry : propz.entrySet()) {
  String[] path = entry.getKey().split('\\.');
  Map<String,Object> parent = root;
  int n = path.length - 1;
  for (int i = 0; i < n; ++i) {
    String p = path[i];
    Object child = parent.get(p);
    if (null == child) {
      Map<String,Object> _p = new HashMap<>();
      parent.put(p, _p);
      parent = _p;      
    } else if (child instanceof Map) {
      parent = (Map<String,Objext>) child;
    } else {
      // it is up to you to do something when the path extends beyond a "final" key
    }
  }
  parent.put(path[n], entry.getValue());
}

然而,这是一个&#34;重新发明轮子&#34;模式,其他答案指出你可能比自己做更好的解决方案。这个例子也向您展示了一种问题:

p1=foobar
p1.p2=foobar

在机器生成属性的情况下,这不会发生,并且异常可能是最佳答案。但在人为操纵属性的情况下,这可能有一些意义。

另一方面,由于Java 7附带了JAXB,您也可以使用完整的XML来完成,而无需额外的库。并使用某种层次结构。