Java的类型安全配置读/写库?

Java的类型安全配置读/写库?,java,configuration,Java,Configuration,是否有一个好的Java配置库可以让我以类型安全的方式读取设置?例如,使用我精心编制的IConfiguration接口,声明getter和setter,并允许我通过它读取/写入配置 使用properties.getProperty(“group.setting”)读取设置,然后将其转换为所需类型,这有点无聊。Apache commons配置允许使用类似于config.getDouble(“number”)的东西,但是这里的“number”又是一个字符串,我希望能够执行类似于double value

是否有一个好的Java配置库可以让我以类型安全的方式读取设置?例如,使用我精心编制的IConfiguration接口,声明getter和setter,并允许我通过它读取/写入配置


使用
properties.getProperty(“group.setting”)
读取设置,然后将其转换为所需类型,这有点无聊。Apache commons配置允许使用类似于
config.getDouble(“number”)
的东西,但是这里的“number”又是一个字符串,我希望能够执行类似于
double value=config.GetNumber()

的操作,因为java不是一种动态语言。实现这一点的唯一方法是使用代码生成器获取属性文件并生成配置类。或者手动为每个属性添加一个getter


我认为commons配置是最好的方式。

通过使用XStream序列化配置类,您应该能够获得一些动力。但缺点是:

  • 配置文件将不是标准属性文件格式之一。它将是任意的XML
  • 序列化格式将是脆弱的。对配置类的微小更改可能导致旧配置文件无法读取

另一方面,基于任意XML的格式可以表示结构比标准属性文件格式好得多的配置项。

如果您有以下配置界面:

public interface IConfig {
  int getNumber();
  void setNumber(int number);

  String getSomeProperty();
  void setSomeProperty(String someProperty);
}
然后,您可以使用将方法映射到属性:

public class ConfigWrapper implements InvocationHandler {
  @SuppressWarnings(value="unchecked")
  public static <T> T wrap(Class c, Properties p) {
    return (T)Proxy.newProxyInstance(c.getClassLoader(), new Class[] {c},
        new ConfigWrapper(p));
  }

  private final Properties properties;

  private ConfigWrapper(Properties p) {
    this.properties = p;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) {
    if(method.getName().startsWith("get")) {
      if(method.getReturnType().equals(int.class)) {
        return Integer.parseInt(
            this.properties.getProperty(method.getName().substring(3)));
      } else if(method.getReturnType().equals(String.class)) {
        return this.properties.getProperty(method.getName().substring(3));
      } else {
        // obviously in a real application you'd want to handle more than just
        // String and int
        throw new RuntimeException(method.getName() + " returns unsupported type: "
            + method.getReturnType());
      }
    } else if(method.getName().startsWith("set")) {
      this.properties.setProperty(method.getName().substring(3),
          args[0].toString());
      return null;
    } else {
      throw new RuntimeException("Unknown method: " + method.getName());
    }
  }
}
调用其中一个接口方法将导致调用
ConfigWrapper.invoke()
,该调用将更新或检索Properties对象(取决于调用的是getter还是setter)

请注意,此实现明显不安全,因为:

  • 在调用getter之前,不会验证Properties对象中已有的值
  • setter和getter不必接受/返回相同的类型
我不知道有哪个库可以这样做,可能是因为Properties对象在其所能描述的配置方面相当有限。

我的库(已经成熟并有很好的文档记录,但并不广为人知)提供了您想要的大部分内容

特别是,Config4J为内置类型(如字符串、布尔值、整数、浮点值和持续时间(如
“500毫秒”
“2.5天”
)提供了类型安全的“查找”(即“获取”)操作。持续时间字符串将自动转换为表示(您选择的)毫秒或秒的整数值

该库还提供了构造块,因此您可以对格式为
”的字符串执行类型安全查找(例如,距离为
“2厘米”和
“10.5米”或
(例如,货币为
“$0.99”
ӣ10.00

该库还提供了一个简单易用的模式验证器(以防您感兴趣)

Config4J无法满足您所述要求的原因是库的“插入”(即“放置”)功能仅在字符串方面起作用。因此,您必须将表示持续时间/任意值的int/boolean/float/int转换为字符串,然后将其“插入”到Config4J对象中。但是,转换为字符串通常不是一项繁重的任务

将一些名称=值对插入Config4J对象后,可以调用
dump()
将整个对象序列化为字符串,然后将其写回配置文件


阅读“入门指南”(,)的第2章和第3章,您应该可以对Config4J有一个足够好的概述,以确定它是否适合您的需要。您可能还想看看源代码下载(,)中提供的“简单封装”演示。

您可以使用XSD定义XML配置文件,然后使用XJC生成源代码。每个XSD类型都映射到一个Java类,您可以轻松地封送/解封

举个例子。XSD:

<xsd:simpleType name="GroupType">
  <xsd:restriction base="xsd:int">
    <xsd:minInclusive value="1"/>
    <xsd:maxInclusive value="255"/>
  </xsd:restriction>
</xsd:simpleType>
摘自教程:


库可以满足您的需要。

我认为typesafe的配置库是您可能需要的。这是你的电话号码

它是一个类型安全库。以下是有关如何使用此库的示例:

import com.typesafe.config.ConfigFactory

Config conf = ConfigFactory.load();
int bar1 = conf.getInt("foo.bar");
Config foo = conf.getConfig("foo");
int bar2 = foo.getInt("bar");
我推荐这个库的主要原因是它可以读取HOCON文件。它代表“人类优化配置对象表示法”,是JSON的超集:

{
    "foo" : {
        "bar" : 10,
        "baz" : 12
    }
}
它有许多特性,使其更具可读性。比如省略特殊字符(
{}
)。最酷的事情是继承:

standard-timeout = 10ms
foo.timeout = ${standard-timeout}
bar.timeout = ${standard-timeout}
如果使用对象值复制字段,则对象将与最后一个对象合并。因此:

foo = { a : 42, c : 5 }
foo = { b : 43, c : 6 }
指与以下内容相同:

foo = { a : 42, b : 43, c : 6 } 

请查看该项目的自述文件,以了解有关此伟大配置库的更多信息

谢谢,我会查看。顺便说一句,网站的第一章在哪里我只看到两个-4@FractalizeR:在www.config4star.org网站上,向下滚动至“下载手册”部分,您将能够访问所有手册。
foo = { a : 42, c : 5 }
foo = { b : 43, c : 6 }
foo = { a : 42, b : 43, c : 6 }