应用程序属性持久化的好方法是什么?

7

我有一系列不同类型的应用程序属性。

这些类型可能包括布尔值、日期、时间戳或字符串。

我需要能够为管理员用户提供更改这些属性的功能,并使系统记住/将它们持久化到文件中。

我正在寻找一种最佳实践方法来存储这些应用程序属性,并能够在更改时持久化它们并在启动时加载它们。


2
“...将它们持久化到离线存储中。” - 我真的不认为你是这个意思。离线存储会像磁带归档器一样。 - Stephen C
@Stephen C,非常公正的评论,我把它改成了“一个文件”。 - JavaRocky
8个回答

4

我最终做的是从java.util.prefs.Preferences中复制一些代码,并在自己的Properties支持的类中使用它,因为Preferences类实际上是用于系统和用户首选项的,不允许我轻松地将其保存在指定位置。 - JavaRocky

4

如果您有存储和读取不同类型属性的需求,例如布尔值、整数等,我认为java.util.prefs API是一个不错的选择。它允许您存储和读取各种数据类型。

这里是API文档


+1 Preferences API很奇怪,不太控制数据存储的方式,但它是比Properties更新的API,是更好的选择。 - Denis Tulskiy
有没有可靠的库可以用于基于文件的java.util.prefs.Preferences实现? - JavaRocky
太阳的JDK实现将它们存储在文件系统中,用于用户首选项(Preferences.geUserRoot()),在用户的主目录中,以XML文件的形式。Preferences类API文档定义了这些文件的DTD。 - naikus
谢谢您的回复。我想控制文件存储的位置。用户的主目录对我的应用程序不合适。我想将其与我的应用程序中的其他文件数据一起存储。太阳jdk的实现是否允许此操作?或者有其他实现可以做到吗? - JavaRocky
1
是的,你可以这样做。你需要有一个实现了java.util.prefs.PreferencesFactory接口的类,该接口返回一个继承自AbstractPreferences的类。所有抽象方法都很简单明了,应该不难实现。事实上,你的Preferences实现可以由java.util.Properties(文件)支持。 - naikus

2

java.util.Properties 是最简单的方法。可以从属性文件 (一个包含 name=value 格式属性的文件) 或简单的 XML 文件创建 Properties 对象。您可以在内存中修改对象,然后将其写回属性或 XML 文件。

如果需要更大的灵活性来构建属性,可以考虑设计自己的XML配置文件,尽管读写可能需要更多的工作。但是您可以使用像 JAXB、XStream 等序列化/反序列化 API,使任务更加容易。

这些文件也可以很容易地手动修改。


1

我使用这段代码,对我来说效果非常好(只是部分代码,从记忆中编写..): (这与Java的Properties类一起使用,但它使添加属性和保持属性文件模板同步更容易。)

to use:
Date date = Conf.value(Prop.SOME_DATE,Date.class);

并且

enum Prop {
    SOME_DATE(Date.class, "2009-10-28", "Some date"){
        Object parse(String value){
            return new Date(value);
        }};
    private final Class<?> type;
    private final String description;
    private final Object default;
    Properties(Class<?> type, String defaultValue, String desc){
       this.type = type;
       this.description = desc;
       this.default = this.parse(defaultValue);
    }
    abstract Object parse(String value);
}

并且

class Conf {
    private static final String PROP_FILE_NAME = "some.properties";
    private volatile Map<Prop,Object> store;

    public void load(){
        //Read from property file and use default if not given.
        //I code it in a way that it will not permit null as value, so 
        //if default is null the user is forced to provide setting.
    }

    public <T> T value(Prop prop, Class<T> clazz){
        return (T)this.store.get(prop);
    }
    public static void main(String[] args){
        //code to autogenerate property file
        //Something like:
        //#Default : 2009-10-28 Description : Some date. Type:Date
        //#SOME_DATE=2009-10-28
    }
}

class 参数让方法有点啰嗦,但有时如果只能让 Java 推断类型会很烦人,就像这样:

CountDownLatch latch = Conf.value(Prop.SOME_INTEGER);
//Compilation error! Since it expects int and won't unbox.

CountDownLatch latch = Conf.value(Prop.SOME_ITEGER,Integer.class);
//Verbose, but works everytime. Of course you could get a 
//ClassCastException, but you should notice that early 
//in the development...    

你把它们记在脑子里了吗? - Rosdi Kasim
啊,这是我经常使用的代码片段,所以我大概记得。但它太小了,不值得打包成一个jar文件 :) - Enno Shioji
是的,这正是它应该工作的方式。只需要一个简单的50行库,就可以自动完成所有这些操作...如果在20年前Java世界中不存在这个功能,我认为这有点令人遗憾。 - peterh

1

也许应该安装一个虚拟机,这样数据库就真正做到了跨平台。这将是真正的Java解决方案。;-( - peterh

0

你可以将它们存储在数据库中,但由于属性的数据类型不同,你必须以字符串表示形式存储它们。你可以使用另一列来指定数据类型。

这种应用程序参数化的形式是我在工作中成功使用过的。这是一个大致的想法,希望你能用这个方法找到解决方案。


0

您可以使用SQLite, Firefox使用它来持久化属性。


有一句很好的英语谚语: "使用大锤砸坚果"。 - peterh

0

尽管您应该使用首选项 API 或属性,但这里有一个可能也有效的技巧:

创建一个 HashMap<String,Object> 并使用 XMLEncoder/XMLDecoder 进行保存/加载。大多数标准 Java 类可以通过此方式序列化为 Java Bean。您可以创建一个简单的包装类来获取各种属性、处理默认值等。这样,您还可以存储嵌套集合,有时非常方便。它真的很容易实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接