37

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

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

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

就我而言,SOAP/WS 端点只有简单的 Key=>Value 对 (String,String)。

4

5 回答 5

27

请参阅此问题以读取 WAR 文件之外的属性文件。

请参阅此问题以从 JNDI 读取变量值。我相信这是最好的解决方案。您可以使用以下代码读取字符串变量:

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 资源可通过 MBeans 管理控制台获得。其中一些提供了一个图形界面来编辑它们。当进行更改时,最多需要重新启动应用程序。

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

这些是 JNDI 提供的好处:

  • 您可以在 WAR/EAR 文件中定义参数的默认值。
  • 参数很容易在容器中配置。
  • 修改参数值时无需重启容器。
于 2009-06-10T22:21:47.600 回答
11

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

1) 只应使用简单的 name=value 条目

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

这种设置允许我们在每个环境中使用不同的配置,使用一组完全编译的二进制文件进行开发/QA/发布周期。在二进制文件中捆绑密码/等是没有风险的,人们可以分享他们的配置来重现我们看到的问题。

于 2009-06-18T17:38:53.967 回答
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");
   }



}
于 2009-06-08T17:24:34.410 回答
9

你可以只存储一个普通的java属性文件,它位于类路径上并加载属性吗?

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

于 2009-06-12T22:36:09.490 回答
4

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

存储环境属性的数据库表

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

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

  • 这相对容易设置
  • 提供非常简单的方法来控制/更改值
  • 通过使其成为数据库脚本的一部分,它可以很好地集成到流程中
于 2009-06-10T23:28:12.007 回答