简体   繁体   English

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

[英]What is a good method of persisting application properties?

I have a series of application properties which all have different types. 我有一系列应用程序属性,它们都有不同的类型。

The types could include, booleans, dates, timestamps, or strings. 类型可以包括布尔值,日期,时间戳或字符串。

I need to be able to provide the ability for administrative users to change these properties and have the system to remember / persist them to a file. 我需要能够为管理用户提供更改这些属性的能力,并让系统记住/将它们保存到文件中。

I am looking for a best practice way to store these application properties and be able to persist them on change and load them on start up. 我正在寻找一种最佳实践方法来存储这些应用程序属性,并能够在更改时保留它们并在启动时加载它们。

Message from the future: the link is already dead. 来自未来的消息:链接已经死亡。

Java has a facility built specifically for this purpose - Properties. Java有专门为此目的而构建的工具 - 属性。 Here is very good article about it 这是关于它的非常好的文章

https://docs.oracle.com/javase/tutorial/essential/environment/properties.html https://docs.oracle.com/javase/tutorial/essential/environment/properties.html

Since you have a requirement of storing and reading various properties of different types like boolean, integers, etc. I think the java.util.prefs API is a good choice for you. 因为您需要存储和读取不同类型的各种属性,如布尔值,整数等。我认为java.util.prefs API是一个不错的选择。 It allows you to store and read various data types. 它允许您存储和读取各种数据类型。

Here's the API documentation 这是API文档

java.util.Properties is the easiest way. java.util.Properties是最简单的方法。 A Properties object can be created from a properties file (a file containing properties in the format name=value ) or even a simple XML file. 可以从属性文件(包含格式为name=value的属性的文件)甚至是简单的XML文件创建Properties对象。 You can modify the object in memory and then write it back to a properties or XML file. 您可以修改内存中的对象,然后将其写回属性或XML文件。

If you need more flexibility in structuring the properties, you can consider designing your own XML configuration file , although it will be a bit more work to read and write. 如果在构造属性时需要更多的灵活性,可以考虑设计自己的XML配置文件 ,尽管读取和写入会有更多的工作量。 You can however use a marshalling/unmarshalling API like JAXB, XStream etc to make that task easier. 但是,您可以使用编组/解组API(如JAXB,XStream等)来简化该任务。

These files can easily be modified manually as well. 这些文件也可以手动修改。

Assuming you are using Java, take a look at apache commons DatabaseConfiguration ( http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/DatabaseConfiguration.html ). 假设您使用的是Java,请查看apache commons DatabaseConfiguration( http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/DatabaseConfiguration.html )。
Basically, what it does is pretty simple. 基本上,它的功能非常简单。 It scans a table that has key-value pairs and exposes that table as a java.util.Properties. 它扫描具有键值对的表,并将该表公开为java.util.Properties。 You can use this to load your application properties from the database. 您可以使用它从数据库加载应用程序属性。
Once loaded, you can cache these properties in your application. 加载后,您可以在应用程序中缓存这些属性。 Remember to invalidate this cache whenever you make changes to the application properties. 每当您更改应用程序属性时,请记住使此缓存无效。

I use this code and it works quite good for me (only partial code, coding from memory..): (This is used in conjunction with the Properties class of java, but it makes it easier to add properties and keep your property file template in sync.) 我使用这个代码,它对我来说非常好(只有部分代码,从内存编码..):(这与java的Properties类一起使用,但它更容易添加属性并保留属性文件模板同步中。)

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

and

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

and

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
    }
}

The class argument makes the method a little verbose, but sometimes it is irritating if you can only let java infer the type, like this: 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...    

You can store them in your Database, however due to the difference in data types of your properties you'll have to store them in their String representation. 您可以将它们存储在数据库中,但是由于属性的数据类型不同,您必须将它们存储在String表示形式中。 You could use another column to specify maybe the data type. 您可以使用另一列来指定数据类型。

That form of application parametrization is something you've used successfully at my work. 这种形式的应用程序参数化是您在我的工作中成功使用的。 That's the general idea, I hope you could arrive to your solution with this. 这是一般的想法,我希望你能用这个来达到你的解决方案。

您可以使用SQLite Firefox使用它来保存属性

Even though you should use Preferences API or Properties, here is a hack that might also work: 即使您应该使用Preferences API或Properties,这里也可能有效:

Create a HashMap<String, Object> and use XMLEncoder/XMLDecoder for saving/loading. 创建HashMap<String, Object>并使用XMLEncoder / XMLDecoder进行保存/加载。 Most of the standard java classes can be serialized this way as java beans. 大多数标准java类都可以像java bean一样序列化。 You can make a simple wrapper class for getting various properties, handling default values etc. This way you can also store nested collections which is handy sometimes. 您可以创建一个简单的包装类来获取各种属性,处理默认值等。这样您还可以存储嵌套的集合,这有时很方便。 It's really easy to implement. 这很容易实现。

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

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