简体   繁体   English

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

[英]Type-safe configuration read/write library for Java?

Is there a good configuration library for Java which will allow me to read settings in a type-safe way? 是否有一个很好的Java配置库,它允许我以类型安全的方式读取设置? For example by taking my crafted IConfiguration interface with getters and setters declared and allowing me to read/write configuration via it. 例如,通过我的精心设计的IConfiguration接口声明getter和setter,并允许我通过它读/写配置。

It's a bit boring to read settings using properties.getProperty("group.setting") and then cast it to needed type. 使用properties.getProperty("group.setting")读取设置然后将其转换为所需类型有点无聊。 Apache commons configuration allows to use something like config.getDouble("number") , but "number" here is a string again and I would like to be able to do something like double value = config.GetNumber() . Apache commons配置允许使用类似config.getDouble("number") ,但“number”这里再次是一个字符串,我希望能够做类似double value = config.GetNumber()

OWNER可以满足您的需求。

I think typesafe's config library is what you might need. 我认为typesafe的配置库是你可能需要的。 Here is the link 这是链接

It is a type-safe library. 它是一个类型安全的库。 Here is an example on how to use this library: 以下是如何使用此库的示例:

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");

The main reason why I recommend this library is that it can read HOCON files. 我推荐这个库的主要原因是它可以读取HOCON文件。 It stands for "Human-Optimized Config Object Notation" and is a superset of JSON: 它代表“Human-Optimized Config Object Notation”,是JSON的超集:

{
    "foo" : {
        "bar" : 10,
        "baz" : 12
    }
}

It has many features to make it more readable. 它具有许多功能,使其更具可读性。 Like omitting special characters ( , , : , {} ). 就像忽略特殊字符( ,:{} And the coolest things is inheritance: 而最酷的事情就是继承:

standard-timeout = 10ms
foo.timeout = ${standard-timeout}
bar.timeout = ${standard-timeout}

And if you duplicate a field with an object value, then the objects are merged with last-one-wins. 如果您复制具有对象值的字段,则对象将与last-one-wins合并。 So: 所以:

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

means the same as: 意思是:

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

Please look at the project's readme file to find more about this great configuration library https://github.com/typesafehub/config 请查看该项目的自述文件以查找有关此出色配置库的更多信息https://github.com/typesafehub/config

You can define an XML configuration file with XSD and then generate JAXB source code with XJC. 您可以使用XSD定义XML配置文件,然后使用XJC生成JAXB源代码。 Every XSD type is mapped to a Java class, which you can easily marshal/unmarshal 每个XSD类型都映射到一个Java类,您可以轻松地编组/解组

An example. 一个例子。 XSD: XSD:

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

Resulting Java code: 产生的Java代码:

public class ElementType {
    @XmlAttribute(name = "Group", required = true)
    protected int group;

    public int getGroup() {
        return group;
    }
    public void setGroup(int value) {
        this.group = value;
    }
}

Taken from the tutorial: 摘自教程:

http://jaxb.java.net/tutorial/ http://jaxb.java.net/tutorial/

If you have a configuration interface such as: 如果您有配置界面,例如:

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

  String getSomeProperty();
  void setSomeProperty(String someProperty);
}

then you could use a Proxy to map the methods to properties: 然后你可以使用代理将方法映射到属性:

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());
    }
  }
}

To use: 使用:

Properties p = new Properties();

IConfig config = wrap(IConfig.class, p);

config.setNumber(50);
config.setSomeProperty("some value");
System.out.println(config.getNumber());
System.out.println(config.getSomeProperty());
System.out.println(p);

Calling one of the interface methods results in a call to ConfigWrapper.invoke() , which updates or retrieves from the Properties object (depending on whether you called a getter or setter). 调用其中一个接口方法会导致调用ConfigWrapper.invoke() ,它会从Properties对象更新或检索(取决于您是否调用了getter或setter)。

Note that this implementation is distinctly unsafe since: 请注意,此实现明显不安全,因为:

  • values already in the Properties object aren't validated until the getter is called 在调用getter之前,不会验证Properties对象中已有的值
  • setter and getter don't have to accept/return the same type setter和getter不必接受/返回相同的类型

I'm not aware of an existing library to do this, maybe because Properties objects are fairly limited in terms of the configuration they can describe. 我不知道现有的库可以做到这一点,可能是因为Properties对象在他们可以描述的配置方面相当有限。

My Config4J library (which is mature and well-documented but not widely known) provides most of what you want. 我的Config4J库(成熟且文档齐全但未广为人知)提供了您想要的大部分内容。

In particular, Config4J provides type-safe "lookup" (that is, "get") operations for built-in types such as string, boolean, int, float, and durations (such as "500 milliseconds" or "2.5 days" ). 特别是,Config4J为内置类型提供类型安全的“查找”(即“get”)操作,例如字符串,布尔值,整数,浮点数和持续时间(例如"500 milliseconds""2.5 days" ) 。 A duration string is automatically converted to an integer value denoting (your choice of) milliseconds or seconds. 持续时间字符串自动转换为表示(您选择)毫秒或秒的整数值。

The library also provides building blocks so you can perform type-safe lookups on strings of the form "<float> <units>" (for example, "2 cm" and "10.5 meters" for distances) or "<units> <float>" (for example, "$0.99" or "£10.00" for money). 该库还提供了构建块,因此您可以对"<float> <units>"形式的字符串执行类型安全查找(例如,距离为"2 cm""10.5 meters" )或"<units> <float>" (例如, "$0.99""£10.00"的钱)。

The library also provides a trivial-to-use schema validator (in case that is of interest to you). 该库还提供了一个简单易用的模式验证器(如果您感兴趣的话)。

The way Config4J fails to meet your stated requirements is that the "insert" (that is, "put") functionality of the library works only in terms of strings. Config4J无法满足您声明的要求的方式是库的“插入”(即“put”)功能仅在字符串方面有效。 So you would have to convert an int/boolean/float/int-denoting-duration/whatever value into a string and then "insert" that into the Config4J object. 因此,您必须将int / boolean / float / int-denoting-duration / whatever值转换为字符串,然后将其“插入”到Config4J对象中。 However, that -to-string conversion is not usually a burdensome task. 但是,这种到字符串的转换通常不是一项繁重的任务。

After inserting some name=value pairs into the Config4J object, you can then call dump() to serialise the entire object into a string that you can then write back to a configuration file. 在将一些name = value对插入Config4J对象后,您可以调用dump()将整个对象序列化为一个字符串,然后您可以将其写回配置文件。

Reading Chapters 2 and 3 of the "Getting Started Guide" ( PDF , HTML ) should give you an a good-enough overview of Config4J to decide if it fits your needs. 阅读“入门指南”( PDFHTML )的第2章和第3章,可以为您提供一个足够好的Config4J概述,以确定它是否符合您的需求。 You might also want to look at the "simple-encapsulation" demo, which is supplied in the source-code download ( compressed tar , zip ). 您可能还想查看“简单封装”演示,该演示在源代码下载( 压缩tarzip )中提供。

I don't think so, because java is not a dynamic language. 我不这么认为,因为java不是动态语言。 The only way this is achievable is if you had a code generator that would get your properties file and generate the configuration class. 这是可以实现的唯一方法是,如果您有一个代码生成器,它将获取您的属性文件并生成配置类。 Or if you manually add a getter for each property. 或者,如果您为每个属性手动添加一个getter。

commons-configuration is the best way to go, I think. 我认为,公共配置是最好的方法。

You should be able to get some traction by using XStream to serialize the configuration class. 通过使用XStream序列化配置类,您应该能够获得一些牵引力。 But the downsides are: 但缺点是:

  • The config file won't be in one of the standard properties file formats. 配置文件不是标准属性文件格式之一。 It will be arbitrary XML instead. 它将是任意XML。
  • The serialization format will be fragile. 序列化格式将是脆弱的。 Minor changes to the configuration class could render old config files unreadable. 对配置类的微小更改可能导致旧配置文件不可读。

On the upside, a format based on arbitrary XML can represent configuration items that have structure much better than the standard properties file formats can. 从好的方面来说,基于任意XML的格式可以表示结构比标准属性文件格式更好的配置项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM