是否有一个很好的Java配置库,它允许我以类型安全的方式读取设置?例如,通过我的精心设计的IConfiguration接口声明getter和setter,并允许我通过它读/写配置。
使用properties.getProperty("group.setting")
读取设置然后将其转换为所需类型有点无聊。 Apache commons配置允许使用config.getDouble("number")
之类的东西,但这里的“number”再次是一个字符串,我希望能够做double value = config.GetNumber()
之类的事情。
答案 0 :(得分:8)
OWNER库可以满足您的需求。
答案 1 :(得分:4)
我认为typesafe的配置库是您可能需要的。这是link
这是一个类型安全的库。以下是如何使用此库的示例:
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}
如果您复制带有对象值的字段,则对象将与last-one-wins合并。所以:
foo = { a : 42, c : 5 }
foo = { b : 43, c : 6 }
表示与:
相同foo = { a : 42, b : 43, c : 6 }
请查看该项目的自述文件,以了解有关此出色配置库的更多信息https://github.com/typesafehub/config
答案 2 :(得分:3)
您可以使用XSD定义XML配置文件,然后使用XJC生成JAXB源代码。每个XSD类型都映射到一个Java类,您可以轻松地编组/解组
一个例子。 XSD:
<xsd:simpleType name="GroupType">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="255"/>
</xsd:restriction>
</xsd:simpleType>
生成的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;
}
}
取自教程:
答案 3 :(得分:2)
如果您有配置界面,例如:
public interface IConfig {
int getNumber();
void setNumber(int number);
String getSomeProperty();
void setSomeProperty(String someProperty);
}
然后您可以使用Proxy将方法映射到属性:
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());
}
}
}
使用:
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);
调用其中一个接口方法会调用ConfigWrapper.invoke()
,该属性将从Properties对象更新或检索(取决于您是否调用了getter或setter)。
请注意,此实现明显不安全,因为:
我不知道有一个现有的库可以做到这一点,可能是因为Properties对象在他们可以描述的配置方面相当有限。
答案 4 :(得分:2)
我的Config4J库(已成熟且记录完备,但未广为人知)提供了您想要的大部分内容。
特别是,Config4J为内置类型提供了类型安全的“查找”(即“get”)操作,例如string,boolean,int,float和durations(例如"500 milliseconds"
或{ {1}})。持续时间字符串会自动转换为表示(您选择的)毫秒或秒的整数值。
该库还提供了构建块,因此您可以对"2.5 days"
形式的字符串执行类型安全查找(例如,"<float> <units>"
和"2 cm"
距离)或{{1} (例如,"10.5 meters"
或"<units> <float>"
为了钱)。
该库还提供了一个简单易用的模式验证器(如果您感兴趣的话)。
Config4J无法满足您声明的要求的方式是库的“插入”(即“put”)功能仅在字符串方面有效。因此,您必须将int / boolean / float / int-denoting-duration / whatever值转换为字符串,然后将其“插入”到Config4J对象中。但是,这种到字符串的转换通常不是一项繁重的任务。
在将一些 name = value 对插入Config4J对象后,您可以调用"$0.99"
将整个对象序列化为一个字符串,然后您可以将其写回配置文件。
阅读“入门指南”(PDF,HTML)的第2章和第3章,应该为您提供一个足够好的Config4J概述,以确定它是否符合您的需求。您可能还想查看源代码下载(compressed tar,zip)中提供的“简单封装”演示。
答案 5 :(得分:0)
我不这么认为,因为java不是动态语言。这是可以实现的唯一方法是,如果您有一个代码生成器,它将获取您的属性文件并生成配置类。或者,如果您为每个属性手动添加一个getter。
我认为commons-configuration是最好的方法。
答案 6 :(得分:0)
通过使用XStream序列化配置类,您应该能够获得一些牵引力。但缺点是:
从好的方面来看,基于任意XML的格式可以表示结构比标准属性文件格式更好的配置项。