如何在 EAR 或 WAR 之外存储 Java EE 配置参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/965061/
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
How can I store Java EE configuration parameters outside of an EAR or WAR?
提问by Martin K.
I want to store configuration for a web project outside of the web project (ear/war file). The application shouldn't know in which container it's running (WebSphere/JBoss etc.).
我想在 web 项目(ear/war 文件)之外存储 web 项目的配置。应用程序不应该知道它在哪个容器中运行(WebSphere/JBoss 等)。
What is the best way to handle this?
处理这个问题的最佳方法是什么?
Is JNDI a clean way? If JNDI can solve my problems, how should I configure it? (Custom Objects?)
JNDI 是一种干净的方式吗?如果 JNDI 可以解决我的问题,我应该如何配置它?(自定义对象?)
In my case are there only simple Key=>Value pairs (String,String) for SOAP/WS endpoints.
就我而言,SOAP/WS 端点只有简单的 Key=>Value 对 (String,String)。
采纳答案by kgiannakakis
See this questionfor reading properties file outside of the WAR file.
请参阅此问题以读取 WAR 文件之外的属性文件。
See this questionfor reading variable values from JNDI. I believe that this is the best solution. You can read a String variable with this code:
请参阅此问题以从 JNDI 读取变量值。我相信这是最好的解决方案。您可以使用以下代码读取 String 变量:
Context initialContext = new InitialContext();
String myvar = (String) initialContext.lookup("java:comp/env/myvar");
The above code will work on all containers. In Tomcat you declare the following in conf/server.xml:
上面的代码适用于所有容器。在 Tomcat 中,您在 conf/server.xml 中声明以下内容:
<GlobalNamingResources ...>
<Environment name="myvar" value="..."
type="java.lang.String" override="false"/>
</GlobalNamingResources>
The above will create a global resource. It is also possible to define a resource in the context of application. In most containers the JNDI resources are available through a MBeans Management Console. Some of them offer a graphical interface to edit them. At most an application restart is needed, when a change is made.
以上将创建一个全局资源。也可以在应用程序的上下文中定义资源。在大多数容器中,JNDI 资源可通过 MBean 管理控制台获得。其中一些提供图形界面来编辑它们。当进行更改时,最多需要重新启动应用程序。
How JNDI resources are defined and edited is container specific. It is the job of the configurator/administrator to apply the appropriate settings.
JNDI 资源的定义和编辑方式是特定于容器的。应用适当的设置是配置人员/管理员的工作。
These are the benefits offered by JNDI:
这些是 JNDI 提供的好处:
- You can define default values of the parameters in the WAR/EAR file.
- Parameters are easily configurable at the container.
- You don't need to restart the container when you modify the value of a parameter.
- 您可以在 WAR/EAR 文件中定义参数的默认值。
- 参数可以在容器中轻松配置。
- 修改参数值时不需要重启容器。
回答by Jared
I use an environment variable to point to a URL (which probably is a file:// URL) that has my configuration in it. This is very simple to setup and doesn't require the JNDI infrastructure.
我使用环境变量指向包含我的配置的 URL(可能是 file:// URL)。这设置起来非常简单,不需要 JNDI 基础设施。
Here's some sample code (typed from memory - I haven't compiled/tested this):
这是一些示例代码(从内存中输入 - 我还没有编译/测试过):
public void loadConfiguration() {
String configUrlStr = System.getenv("CONFIG_URL"); // You'd want to use a more
// Specific variable name.
if(configUrlStr == null || configUrlStr.equals("") {
// You would probably want better exception handling, too.
throw new RuntimeException("CONFIG_URL is not set in the environment.");
}
try {
URI uri = new URI(configUrlStr);
File configFile = new File(uri);
if(!configFile.exists()) {
throw new RuntimeException("CONFIG_URL points to non-existant file");
}
if(!configFile.canRead()) {
throw new RuntimeException("CONFIG_URL points to a file that cannot be read.");
}
this.readConfiguration(configFile);
} catch (URISyntaxException e) {
throw new RuntimeException("Malformed URL/URI in CONFIG_URL");
}
}
回答by Kartik Shah
My favorite places are : Environment Variables and Properties files (as suggested by Jared and kgiannakakis above.)
我最喜欢的地方是:环境变量和属性文件(如上面的 Jared 和 kgiannakakis 所建议的。)
Database Table storing environment properties
数据库表存储环境属性
However one other simpler solutions is to have Database table storing environment properties.
然而,另一种更简单的解决方案是让数据库表存储环境属性。
If your application uses database
如果您的应用程序使用数据库
- this is relatively easy to setup
- Gives really easy way to control/change values
- It can be integrated in the process well by making it part of DB scripts
- 这相对容易设置
- 提供非常简单的方法来控制/更改值
- 通过使其成为 DB 脚本的一部分,它可以很好地集成到流程中
回答by Aaron Saunders
you can just store then is a normal java properties file that is on the class path and just load the properties?
你可以只存储一个普通的java属性文件,它在类路径上并加载属性?
it is straightforward and pretty simple.. unless I am missing something
它很简单也很简单……除非我遗漏了什么
回答by Jason Thrasher
We had a similar configuration requirement when deploying a webapp for different developers, and on Amazon's EC2: how do we separate configuration from the binary code? In my experience, JNDI is too complex, and varies too much between containers to be used. Also, hand-editing XML is very susceptible to syntax errors, so was the idea was thrown out. We resolved this with a design based on a few rules:
在为不同的开发人员部署 web 应用程序时,以及在 Amazon 的 EC2 上,我们有类似的配置要求:我们如何将配置与二进制代码分开?根据我的经验,JNDI 太复杂了,并且在要使用的容器之间变化太大。此外,手工编辑 XML 非常容易出现语法错误,因此这个想法被抛弃了。我们通过基于一些规则的设计解决了这个问题:
1) only simple name=value entries should be used
1) 只应使用简单的 name=value 条目
2) new configurations should be loadable by changing only one parameter
2) 新的配置应该只改变一个参数就可以加载
3) our WAR binary must be reconfigurable w/o repackaging it
3) 我们的 WAR 二进制文件必须是可重新配置的,无需重新打包
4) sensitive parameters (passwords) will never be packaged in the binary
4)敏感参数(密码)永远不会被打包成二进制
Using .properties files for all configuration, and using System.getProperty("domain");
to load the appropriate properties files, we were able to meet the requirements. However, the system property does not point to a file URL, instead we created a concept we call "domain" to specify the configuration to use. The location of the configuration is always:$HOME/appName/config/$DOMAIN.properties
.
使用 .properties 文件进行所有配置,并使用System.getProperty("domain");
加载适当的属性文件,我们能够满足要求。但是,系统属性并不指向文件 URL,而是创建了一个称为“域”的概念来指定要使用的配置。配置的位置总是:$HOME/appName/config/$DOMAIN.properties
。
So if I want to run my app using my own configuration, I start the app by setting the domain to my name:-Ddomain=jason
on startup, and the app loads the file:/home/jason/appName/config/jason.properties
This lets developers share configurations so we can recreate the same state of the app for testing and deployment without recompiling or repackaging. The domain value is then used to load .properties from a standard location, outside of the bundled WAR.
因此,如果我想使用我自己的配置运行我的应用程序,我通过将域设置为我的名字-Ddomain=jason
来启动应用程序:在启动时,应用程序加载文件:/home/jason/appName/config/jason.properties
这允许开发人员共享配置,以便我们可以重新创建应用程序的相同状态用于测试和部署,无需重新编译或重新打包。然后使用域值从捆绑的 WAR 之外的标准位置加载 .properties。
I can completely recreate the production environment on my workstation by using the production configuration like:-Ddomain=ec2
which would load:/home/jason/appName/config/ec2.properties
我可以通过使用如下生产配置在我的工作站上完全重新创建生产环境:-Ddomain=ec2
这将加载:/home/jason/appName/config/ec2.properties
This setup allows us to do have dev/QA/release cycles with exactly -one- set of compiled binaries, using different configurations in each environment. There's no risk of having passwords/etc bundled in the binaries, and people can share their configurations to recreate issues that we're seeing.
这种设置允许我们在每个环境中使用不同的配置,使用一组编译好的二进制文件来完成开发/质量检查/发布周期。没有将密码/等捆绑在二进制文件中的风险,人们可以共享他们的配置来重现我们看到的问题。