简体   繁体   中英

What is the simplest way to do settings files in Java?

Obviously enough, I want to avoid hardcoding paths and such into my application, and as a result, I'd like to make a settings file that will store simple things like strings and such. What is the simplest way to do so? I was thinking something along the lines of how Cocoa uses object persistence, but I can't seem to find anything equivalent.

您可以使用使用java.util.Properties类操作的属性文件。

Based on the fact you said simplest:

Please keep in mind I didn't do any exception handling. You will need to do that for the Streams.

    // Save Settings
    Properties saveProps = new Properties();
    saveProps.setProperty("path1", "/somethingpath1");
    saveProps.setProperty("path2", "/somethingpath2");
    saveProps.storeToXML(new FileOutputStream("settings.xml"), "");

    // Load Settings
    Properties loadProps = new Properties();
    loadProps.loadFromXML(new FileInputStream("settings.xml"));
    String path1 = loadProps.getProperty("path1");
    String path2 = loadProps.getProperty("path2");

This depends on how you want your application to be configured and who you expect will configure the application. If you want to use the system's native configuration mechanism (eg PLIST files in ~/Library on Mac OS X, gconf on Gnome, the system registry on Windows), then java.util.prefs.Preferences is the correct and simple way to deal with settings / preferences. You would still probably want to create your own class on top of Preferences with named constants for the keys as well as the default values for these settings, and possibly helper methods to retrieve them. Here is an example of how to use it:

// Class to wrap some settings
public class AnimationSettings {
    private static final String VELOCITY_KEY = "velocity";
    private static final double VELOCITY_DEFAULT = 5.0;

    public static double getVelocity() {
        return getPrefs().getDouble(VELOCITY_KEY, VELOCITY_DEFAULT);
    }

    public static void setVelocity(int velocity) {
         getPrefs().putDouble(VELOCITY_KEY, velocity);
    }

    public static void sync() {
         getPrefs().sync();
    }

    private static Preferences getPrefs() {
        if (preferences_ == null) {
           preferences_ = Preferences.userNodeForPackage(AnimationSettings.class);
        }
        return preferences_;
    }

    private static Preferences preferences_ = null;
};

// Elsewhere in the application:
//...
double velocity = AnimationSettings.getVelocity();
// ...

That said, the Preferences class will not give you a single way to configure your application across platforms, and it doesn't necessarily give you a configuration file. For that, XML / *.properties files are also a possible solution as suggested by some of the other answerers. A downside to using XML and properties files, however, is that you must then deal with where they should go, how you would look them up, whether you want to have multiple such files one overriding the other (eg system settings and user settings), what to do if the file isn't there, etc. Preferences nicely handles these sorts of things.

Have you considered basic object serialization and writing the results to a file? As long as your preferences implement Serializable throughout the graph of preferences objects, you could serialize them out with no problem.

Properties files are good, but they aren't flexible for binary data or persistence.

There are generally two different ways for this. One language specific and one general. The general way to store settings is in a properties file which can be read by the Properties class. Please see this .

The language specific way of storing properties would be to have a properties file for each language and a default one for fallback purpose. You can read these by using the Resource class and providing a locale. Please see this .

If this is a web based application, you can add these as part of the environment variables (or custom properties) within the app server console/file.

If it is a stand-alone application, a simple property file will suffice.

If you are building a web application, use Spring 3.0. You can define beans in web.xml and Dispatcher-servlet.xml files.

In general, web containers like Jetty and Tomcat let you define Environment variables. This has the added benefit of allowing these variables to change from server to server without needing to recompile or rebuild the WAR file.

I typically use this method so I can deploy from development servers to staging servers and to the production servers without needing to constantly fiddle with the code or the WAR file.

I would suggest to you (and to anyone who may be reading this) that you consider the Reflection API . Be warned though that it is generally considered bad practice to use reflection in production code.

You could define a class with all of the different fields in the settings file:

public class Settings {
    public String name;
    public int age;
    public String profilePicturePath;
    public double rating;
}

And your settings file could look something like this:

name=John
age=30
profilePicturePath=images/john.png
rating=8.5

It is important that the field names in the settings file match the field names in the class. If they don't; you could always write a function to convert them (eg, a function to convert a settings file field name with spaces ("Profile Picture Path") to a camelCase name ("profilePicturePath")).

Now you would iterate over all of the strings in the settings file and extract the field name and value from each of them, both as strings. I'm not going to explain how to use reflection here, but the idea is that for each field in the settings file you would use reflection to locate the field in the Settings class with the same name and check it's type. You would then apply the appropriate conversion method to the value from the settings file and use reflection to set the field in a Settings object to the converted value.

Although this approach uses reflection, which is frowned upon, it's beauty lies in the fact that it can be generalized for any field; you don't have to handle each field individually. If you want to add another setting, all you need to do is add two lines: one to your settings file and one to your Settings class. You can also expand this to load enums and perhaps even instances of other classes!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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