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

2022-09-01 05:13:11

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

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

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

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


答案 1

有关读取 WAR 文件外部的属性文件,请参阅此问题

有关从 JNDI 读取变量值的信息,请参阅此问题。我认为这是最好的解决方案。您可以使用以下代码读取 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 资源可通过 MBeans 管理控制台获得。其中一些提供了用于编辑它们的图形界面。在进行更改时,最多需要重新启动应用程序。

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

以下是 JNDI 提供的优势:

  • 您可以在 WAR/EAR 文件中定义参数的缺省值。
  • 参数在容器上易于配置。
  • 修改参数值时无需重新启动容器。

答案 2

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

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

2) 新配置应该只需更改一个参数即可加载

3)我们的WAR二进制文件必须是可重新配置的,没有重新打包它

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

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

因此,如果我想使用自己的配置运行我的应用,我会通过将域设置为我的名字来启动应用:

在启动时,应用加载文件:这允许开发人员共享配置,

以便我们可以重新创建应用的相同状态进行测试和部署,而无需重新编译或重新打包。然后,域值用于从捆绑 WAR 外部的标准位置加载 .properties。-Ddomain=jason/home/jason/appName/config/jason.properties

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

此设置允许我们确实有开发/QA/发布周期,其中包含一组已编译的二进制文件,在每个环境中使用不同的配置。没有将密码/等捆绑在二进制文件中的风险,人们可以共享他们的配置以重新创建我们看到的问题。