我想在Web项目(ear / war文件)之外存储Web项目的配置。 应用程序不应该知道它在哪个容器中运行(WebSphere / JBoss等)。
处理此问题的最佳方法是什么?
JNDI是一个干净的方式吗?如果JNDI可以解决我的问题,我应该如何配置它? (自定义对象?)
在我的情况下,SOAP / WS端点只有简单的Key =>值对(String,String)。
答案 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提供的好处:
答案 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所建议的那样。)
存储环境属性的数据库表
然而,另一个更简单的解决方案是使数据库表存储环境属性。
如果您的应用程序使用数据库