简体   繁体   English

在Java中执行设置文件的最简单方法是什么?

[英]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. 我正在思考Cocoa如何使用对象持久性的方法,但我似乎无法找到任何等价物。

您可以使用使用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. 您需要为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. 如果你想使用系统的本机配置机制(例如Mac OS X上的〜/ Library中的PLIST文件,Gnome上的gconf,Windows上的系统注册表),那么java.util.prefs.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. 您仍然可能希望在Preferences之上创建自己的类,其中包含键的命名常量以及这些设置的默认值,以及可能的帮助方法来检索它们。 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. 也就是说,Preferences类不会为您提供跨平台配置应用程序的单一方法,并且它不一定会为您提供配置文件。 For that, XML / *.properties files are also a possible solution as suggested by some of the other answerers. 为此,XML / * .properties文件也是一些可能的解决方案,正如其他一些回答者所建议的那样。 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. 然而,使用XML和属性文件的一个缺点是,您必须处理它们应该去哪里,如何查找它们,是否要让多个这样的文件覆盖另一个(例如系统设置和用户设置) ,如果文件不在那里该怎么办,等等。优惠很好地处理这些事情。

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. 只要您的首选项在首选项对象的图形中实现Serializable,您就可以毫无问题地将它们序列化。

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. 存储设置的一般方法是属性文件,可以由Properties类读取。 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. 您可以使用Resource类并提供区域设置来阅读这些内容。 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. 如果这是基于Web的应用程序,则可以将这些作为环境变量(或自定义属性)的一部分添加到应用程序服务器控制台/文件中。

If it is a stand-alone application, a simple property file will suffice. 如果它是一个独立的应用程序,一个简单的属性文件就足够了。

If you are building a web application, use Spring 3.0. 如果要构建Web应用程序,请使用Spring 3.0。 You can define beans in web.xml and Dispatcher-servlet.xml files. 您可以在web.xml和Dispatcher-servlet.xml文件中定义bean。

In general, web containers like Jetty and Tomcat let you define Environment variables. 通常,像Jetty和Tomcat这样的Web容器允许您定义环境变量。 This has the added benefit of allowing these variables to change from server to server without needing to recompile or rebuild the WAR file. 这具有允许这些变量从服务器更改为服务器而无需重新编译或重建WAR文件的额外好处。

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. 我通常使用这种方法,因此我可以从开发服务器部署到登台服务器和生产服务器,而无需经常使用代码或WAR文件。

I would suggest to you (and to anyone who may be reading this) that you consider the Reflection API . 我建议您(以及可能正在阅读本文的任何人)考虑使用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")). 您总是可以编写一个函数来转换它们(例如,将带有空格的设置文件字段名称(“Profile Picture Path”)转换为camelCase名称(“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. 我不打算在这里解释如何使用反射,但想法是对于设置文件中的每个字段,您将使用反射来定位具有相同名称的Settings类中的字段并检查它的类型。 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. 然后,您可以将适当的转换方法应用于设置文件中的值,并使用反射将Settings对象中的字段设置为转换后的值。

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. 如果要添加其他设置,您只需添加两行:一行添加到设置文件,另一行添加到Settings类。 You can also expand this to load enums and perhaps even instances of other classes! 您也可以将其展开以加载枚举,甚至可以加载其他类的实例!

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

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