如何在EAR或WAR之外存储Java EE配置参数?

时间:2009-06-08 14:03:10

标签: java parameters java-ee war ear

我想在Web项目(ear / war文件)之外存储Web项目的配置。 应用程序不应该知道它在哪个容器中运行(WebSphere / JBoss等)。

处理此问题的最佳方法是什么?

JNDI是一个干净的方式吗?如果JNDI可以解决我的问题,我应该如何配置它? (自定义对象?)

在我的情况下,SOAP / WS端点只有简单的Key =>值对(String,String)。

5 个答案:

答案 0 :(得分:27)

请参阅此question以获取WAR文件之外的属性文件。

有关从JNDI读取变量值,请参阅此question。我相信这是最好的解决方案。您可以使用以下代码读取String变量:

Context initialContext = new InitialContext();
String myvar = (String) initialContext.lookup("java:comp/env/myvar");

以上代码适用于所有容器。在Tomcat中,您在conf / server.xml中声明以下内容:

<GlobalNamingResources ...>
  <Environment name="myvar" value="..."
         type="java.lang.String" override="false"/>
</GlobalNamingResources>

以上将创建一个全球资源。还可以在应用程序的上下文中定义资源。在大多数容器中,JNDI资源可通过MBean管理控制台获得。其中一些提供了一个图形界面来编辑它们。在进行更改时,最多需要重新启动应用程序。

如何定义和编辑JNDI资源是特定于容器的。配置程序/管理员的工作是应用适当的设置。

这些是JNDI提供的好处:

  • 您可以在WAR / EAR文件中定义参数的默认值。
  • 可以在容器中轻松配置参数。
  • 修改参数值时无需重新启动容器。

答案 1 :(得分:11)

在为不同的开发人员部署webapp时,我们有类似的配置要求,在Amazon的EC2上:我们如何将配置与二进制代码分开?根据我的经验,JNDI太复杂,并且在要使用的容器之间变化太大。此外,手动编辑XML非常容易受到语法错误的影响,因此这个想法被抛弃了。我们通过基于一些规则的设计解决了这个问题:

1)只应使用简单的名称=值条目

2)只需更改一个参数

即可加载新配置

3)我们的WAR二进制文件必须可重新配置,无需重新打包

4)敏感参数(密码)永远不会打包在二进制文件

对所有配置使用.properties文件,并使用System.getProperty("domain");加载相应的属性文件,我们能够满足要求。但是,系统属性不指向文件URL,而是创建了一个我们称之为“域”的概念来指定要使用的配置。配置的位置始终如下:
$HOME/appName/config/$DOMAIN.properties

因此,如果我想使用自己的配置运行我的应用程序,我会通过将域名设置为我的名字来启动应用程序:
-Ddomain=jason
在启动时,应用程序加载文件:
/home/jason/appName/config/jason.properties
这使开发人员可以共享配置,因此我们可以重新创建应用程序的相同状态以进行测试和部署,而无需重新编译或重新打包。然后,域值用于从捆绑的WAR之外的标准位置加载.properties。

我可以使用以下生产配置在工作站上完全重新创建生产环境:
-Ddomain=ec2 哪个会加载:
/home/jason/appName/config/ec2.properties

此设置允许我们在每个环境中使用不同的配置,使用完全一组已编译的二进制文件来进行dev / QA / release周期。没有密码/ etc捆绑在二进制文件中的风险,人们可以共享他们的配置来重新创建我们正在看到的问题。

答案 2 :(得分:10)

我使用环境变量指向一个URL(可能是一个file:// URL),其中包含我的配置。这非常简单,不需要JNDI基础设施。

这是一些示例代码(从内存中输入 - 我没有编译/测试过这个):

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



}

答案 3 :(得分:9)

你可以只是存储然后是类路径上的普通java属性文件,只是加载属性?

它很简单,很简单..除非我遗漏了什么

答案 4 :(得分:4)

我最喜欢的地方是:环境变量和属性文件(如上面的Jared和kgiannakakis所建议的那样。)

存储环境属性的数据库表

然而,另一个更简单的解决方案是使数据库表存储环境属性。

如果您的应用程序使用数据库

  • 这相对容易设置
  • 提供非常简单的方法来控制/更改价值
  • 通过将其作为数据库脚本的一部分,可以很好地集成到流程中