Java 管理配置数据的最佳方法是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2324109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to manage configuration data
提问by Shekhar
I am working on a product suite which has 4 products. Right now, all of the configuration data is either in the XML or properties files.This approach is not maintainable as we have to manage different configuration file for different environment(for e.g. Production, Development etc).
我正在开发一个包含 4 个产品的产品套件。现在,所有的配置数据都在 XML 或属性文件中。这种方法是不可维护的,因为我们必须为不同的环境(例如生产、开发等)管理不同的配置文件。
So, what is the best way to handle configuration data?
那么,处理配置数据的最佳方法是什么?
Also, can we modularize this into a separate module? So that all products can use this module. We don't want to use the property files. I am looking for a solution in which we can move all of the configuration specific code as a new configuration module and persist all the configuration data in database.
另外,我们可以将其模块化为一个单独的模块吗?这样所有的产品都可以使用这个模块。我们不想使用属性文件。我正在寻找一种解决方案,在该解决方案中,我们可以将所有特定于配置的代码作为新的配置模块移动,并将所有配置数据保存在数据库中。
回答by Bozho
Using commons-configurationyou have a unified API for accessing the properties, no matter howthey are represented - .properties, xml, JNDI, etc. For example:
使用commons-configuration您有一个统一的 API 来访问属性,无论它们如何表示 - .properties、xml、JNDI 等。例如:
config.properties
:
config.properties
:
jdbcHost=192.168.12.35
jdbcUsername=dbuser
jdbcPassword=pass
config.xml
:
config.xml
:
<config>
<jdbcHost>192.168.12.35</jdbcHost>
<jdbcUsername>dbuser</jdbcUsername>
<jdbcPassword>pass</jdbcPassword>
</config>
in both cases they will be accessible with something like:
在这两种情况下,它们都可以通过以下方式访问:
String host = config.getString("jdbcHost");
回答by Nicole
You're almost there... I would keep your same approach and pull in the correct configuration file for the instance of the application that is running by a method similar to either of the following:
你快到了......我会保持你的相同方法并为通过类似于以下任一方法运行的应用程序实例拉入正确的配置文件:
Name all of your configuration files differently and have your application pull them in by some unique criteria (username, hostname, etc.):
- production.properties
- developer1.properties
- developer2.properties
Keep them outside the codebase in a location based on an environment variable that the application assumes exists:
- YOURAPP_CONFIG_DIR/server_config.xml
- YOURAPP_CONFIG_DIR/database_config.properties
以不同的方式命名所有配置文件,并让您的应用程序通过一些独特的标准(用户名、主机名等)将它们拉入:
- 生产属性
- developer1.properties
- developer2.properties
根据应用程序假定存在的环境变量,将它们保留在代码库之外的位置:
- YOURAPP_CONFIG_DIR/server_config.xml
- YOURAPP_CONFIG_DIR/database_config.properties
I've even used a combination of these approaches on the same project (#1 for build process configurations and #2 for runtime configurations).
我什至在同一个项目中使用了这些方法的组合(#1 用于构建过程配置,#2 用于运行时配置)。
回答by zznate
For all of our environments, configuration data lives on the target machines in the form of properties files. We use PropertyPlaceholderconfigurerfrom SpringFramework to bind these properties to our apps to keep things portable accross environments.
对于我们所有的环境,配置数据都以属性文件的形式存在于目标机器上。我们使用SpringFramework 的PropertyPlaceholderconfigurer将这些属性绑定到我们的应用程序,以保持事物在环境中的可移植性。
For example, as long as I know that /etc/myapp/database.properties will be present on whatever machine my app will be running on, then in my spring configuration, I just need something like so:
例如,只要我知道 /etc/myapp/database.properties 将出现在我的应用程序将运行的任何机器上,那么在我的 spring 配置中,我只需要这样的东西:
<bean id="myPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/etc/myapp/database.properties</value>
</list>
</property>
</bean>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://${db.host}:3306/${db.name}" />
<property name="username" value="${db.user}" />
<property name="password" value="${db.pass}" />
</bean>
There are a bunch of options for that Spring class about where properties files can live. You can even make them substitutions and pass them in as environment variables:
该 Spring 类有很多关于属性文件可以存放在哪里的选项。您甚至可以替换它们并将它们作为环境变量传入:
<bean id="myPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="searchSystemEnvironment" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>${database.configuration.file.url}</value>
</list>
</property>
</bean>
And in bash_profile (or whatever): export JAVA_OPTS="-Ddatabase.configuration.file.url=file:///etc/myapp/database.properties"
在 bash_profile(或其他)中:export JAVA_OPTS="-Ddatabase.configuration.file.url=file:///etc/myapp/database.properties"
Or just the same -D option passed in when you call "java" depending on what you are doing.
或者只是在调用“java”时传入相同的 -D 选项,具体取决于您在做什么。
FWIW, we maintain our properties files separately as RPMs.
FWIW,我们将我们的属性文件作为 RPM 单独维护。
回答by Tomislav Nakic-Alfirevic
If your applications work with a database, you can create a "configuration" table as follows:
如果您的应用程序使用数据库,您可以创建一个“配置”表,如下所示:
create table configuration (mode char(3), key varchar(255), value varchar(1023));
You would initialize it using an init script, say init.sql with contents along the lines of:
您可以使用 init 脚本对其进行初始化,比如 init.sql ,内容如下:
insert into configuration values ('pro', 'param1', 'value1'); -- production
insert into configuration values ('dev', 'param1', 'value1'); -- development
insert into configuration values ('tst', 'param1', 'value1'); -- testing
...
The benefits of this approach are as follows:
这种方法的好处如下:
- you version the script together with your code
- you can easily extend it to include per-user or per-group settings by adding a user/group id
- you can change the settings at runtime if you need to do so
- you get to use the same stack (JPA + DAO, Cayenne...) you normally use to handle core application data to handle configuration data
- 您将脚本与代码一起版本化
- 您可以通过添加用户/组 ID 轻松扩展它以包含每个用户或每个组的设置
- 如果需要,您可以在运行时更改设置
- 您可以使用通常用于处理核心应用程序数据以处理配置数据的相同堆栈(JPA + DAO、Cayenne...)
回答by joevartuli
There are plenty of different strategies. All of them are good and depends on what suit you best.
有很多不同的策略。所有这些都很好,取决于什么最适合你。
- Build a single artifact and deploy configs to a separate location. The artifact could have placeholder variables and, on deployment, the config could be read in. Have a look at Springs property placeholder. It works fantastically for webapps that use Spring and doesn't involve getting ops involved.
- Have an externalised property config that lives outside of the webapp. Keep the location constant and always read from the property config. Update the config at any stage and a restart will be up the new values.
- If you are modifying the environment (i.e. application server being used or user/group permissions) look at using the above methods with puppet or chef. Also have a look at managing your config files with these tools.
- 构建单个工件并将配置部署到单独的位置。工件可以有占位符变量,并且在部署时可以读入配置。查看 Springs 属性占位符。它非常适用于使用 Spring 且不涉及操作的 web 应用程序。
- 有一个位于 webapp 之外的外部属性配置。保持位置不变并始终从属性配置中读取。在任何阶段更新配置,重新启动将使用新值。
- 如果您正在修改环境(即正在使用的应用程序服务器或用户/组权限),请查看使用 puppet 或 Chef 的上述方法。还可以看看使用这些工具管理您的配置文件。
回答by okwap
Here is an keep simple stupid solution.
这是一个保持简单的愚蠢解决方案。
The code snippet, which try to use the properties file in the current directory first. If failed, use the properties file in resource directory (or in the jar file) instead.
代码片段,首先尝试使用当前目录中的属性文件。如果失败,请改用资源目录(或 jar 文件)中的属性文件。
Properties configFile = new Properties();
try {
configFile.load(new FileInputStream("production.properties"));
} catch (Exception e) {
System.err.println("Can not read properties, try to use default properties file.");
configFile.load(this.getClass().getClassLoader().
getResourceAsStream("development.properties"));
}
回答by Colby Cox
Environment variables are just about the easiest way to go. Set them as you would any other time, access them w/ System.getenv("...")
环境变量几乎是最简单的方法。像其他任何时候一样设置它们,使用它们访问它们System.getenv("...")
回答by Bienvenido David
Configis a configuration file management tool. You can create configuration that is common on all environments, or you can create an environment specific configuration. You can keep using your XML and properties files, and let Config maintain the differences in environment. You can think of Config as your centralized database and it can output the configuration file in the format that you want. Whenever you want your configuration file, just deploy (push or pull) it from Config to your desired location. Note that I'm part of the Config team.
Config是一个配置文件管理工具。您可以创建在所有环境中通用的配置,也可以创建特定于环境的配置。您可以继续使用您的 XML 和属性文件,并让 Config 维护环境差异。您可以将 Config 视为您的集中式数据库,它可以以您想要的格式输出配置文件。无论何时您需要配置文件,只需将其从 Config 部署(推送或拉取)到您想要的位置。请注意,我是 Config 团队的一员。