在jar中包含属性/配置文件是不好的做法吗?

时间:2009-07-30 19:37:21

标签: java configuration properties jar

例如:

MyApp是一个Web应用程序,其中包含一个属性文件(server.properties),用于描述应用程序的配置数据(例如服务器名称)。在开发阶段,server.properties位于自己的IDE项目文件夹中(它的逻辑位置)。

现在是时候部署MyApp了。 IDE使得类文件以及支持配置文件变得非常简单。现在我们只是将Jar放在适当的Web容器中然后我们就去....

一周后...... MyApp使用的服务器配置数据需要更改。哪个更有意义?

一个。在IDE域中修改server.properties文件并生成一个全新的jar文件。重新部署。 (这意味着弹出应用程序以进行简单的配置更改)。

B中。破解已部署的Jar并修改server.properties文件? (如果缓存了server.properties,可能必须在MyApp中调用刷新函数...但不应该要求完整的应用程序反弹。还需要记住修改源server.properties以便将来的部署不会还原server.properties到旧的服务器名称)。

℃。首先将server.properties置于jar文件的外部。与B的流程非常相似,将配置数据保存在jar外部的细微差别(在开发和生产部署之间引入了不同的路径)

d。其他:

谢谢!

11 个答案:

答案 0 :(得分:18)

我和D一起去。

尝试从.jar外部加载属性文件,如果失败,则加载内置于jar中的属性。

这使您可以在每次构建时推出“现成的”配置(还可以降低部署的复杂性,如果仅通过一个文件),同时还可以使覆盖配置成为可能并且相当简单。

答案 1 :(得分:9)

如果您使用Spring,那么您可以使用属性占位符来完成工作。

<!-- try and resolve the config from the filesystem first and then fallback to the classpath -->
<context:property-placeholder location="file:config.properties, classpath:config.properties"
                              ignore-resource-not-found="true"/>

您可以在文件系统和类路径上指定资源,Spring将首先尝试解析文件系统中的所有属性,然后回退到类路径。通过将“ignore-resource-not-found”属性指定为“true”,如果文件系统上不存在该文件并允许它从类路径中解析属性,则会阻止Spring抛出异常。

使用此组合还允许您将属性拆分为两个文件,例如,您可能永远不希望在类路径上的文件中指定密码,并期望在文件系统上从外部指定密码。文件系统中缺少的任何属性都将从类路径中解析。

在包含以下内容的文件夹中

application.jar
config.properties

你应该可以使用:

java -jar application.jar

这是一个示例config.properties供参考:

# This file contains properties that are used to configure the application
database.url=127.0.0.1
database.port=3306
database.user=root
database.pass=p4ssw0rd

答案 2 :(得分:5)

这取决于。如果属性文件包含要由应用程序或库的用户更改的数据,那么它应该位于外部。

如果它包含静态数据并且您创建属性文件只是为了避免编码源代码中的值,或者如果文件是本地化字符串,我会将它们留在jar中。至少因为属性文件邀请人们改变值;)

答案 3 :(得分:5)

d

在jar中加载属性。然后使用jar-ed属性作为默认值创建一个新属性。然后从罐子外面装载。这允许选择属性的自定义。

答案 4 :(得分:3)

请记住,在J2EE中,您无法保证能够从J2EE环境外部访问文件(无法直接访问文件)。

您必须使用JNDI指向包含数据的数据源或部署工件中的属性文件。

例如,Websphere默认情况下不允许直接文件访问。

答案 5 :(得分:2)

通常,这是一个标准,代码应该从测试迁移到生产 UNCHANGED 。这意味着您可能无法编辑嵌入的配置文件。此外,您可能会在需要更改已部署配置的情况下结束 - 这通常非常麻烦。因此,我们将configuraiton留在罐子外面。

对于Java EE应用程序,请考虑JNDI或类路径中的属性文件。

我有一个Web应用程序,其中从邻居Web应用程序中检索配置只是为了将两者分开。事实证明这更容易。

答案 6 :(得分:2)

选项D.在不同的环境中,您可能需要指定想要指定环境属性,例如连接到数据库或代理等。

其他值得注意的事情是,在生产中,您可能希望快速更改属性,而无需预先打包jar或替换jar中的属性文件。

E.g。数据库服务器已经崩溃,您需要指向不同的服务器(如果不使用数据库的负载平衡器)。所以你需要做的就是替换数据库属性并重新启动。你在那里节省了很多时间。

答案 7 :(得分:1)

我在webapps(WARs)中使用属性文件,但主要用于默认值以及或多或少不可变的内容(因为即使可能,webapps也不应该更新它们的WAR)。

对于你所说的内容,我使用JNDI。您可以在web.xml文件中将属性定义为资源。这样,在最坏的情况下,您更新web.xml而不是应用程序本身。

对于某些服务器,有一些方法可以覆盖这些资源值,而根本不会触及WAR。例如,在Tomcat中。

我通常会为测试,Q / A和生产制作一个WAR,并使用Tomcat的Context xml文件覆盖环境敏感资源。我认为这比必须构建多个WAR或修改WARS要好得多,因为我正在测试的应用程序几乎与正在生产的应用程序相同。

答案 8 :(得分:1)

我认为答案取决于您是否认为需要对配置进行版本控制。 (它们可能是生产配置或回归测试的配置......)

  • 如果您不需要版本控制,那么带有覆盖属性文件的外部属性文件的选项D是一个很好的选项。选项B和C对东西更容易接受,但是如果你真的关心你会使用版本控制: - )
  • 如果您需要版本控制,选项A可以提供更多控制,但如果您有可能进行多次部署,您可能还需要/需要版本控制每个部署的配置。一个例子是单独部署到测试和生产平台。

以下是我们如何使用Maven模块和Maven WAR文件“叠加”。

  1. 我们有多个Java代码组件模块。这些是JAR模块。
  2. 我们为静态内容,JSP和核心配置数据(Spring连接,默认属性)提供了“基础webapp”模块。这是一个WAR模块,因此构建的结果是包含上述+所有JAR文件的WAR。
  3. 每个不同的“站点配置”都是WAR模块,其中包含属性,连接文件和内容的特定于站点的覆盖。使用Maven WAR“overlay”机制描述了覆盖,并导致从“基础”WAR和覆盖组合的新WAR。
  4. 所有这些都被检入版本控制,您需要进行Maven构建和WAR部署以进行配置更改。

答案 9 :(得分:0)

我问了一个类似的问题。我们还没有想到这一切。但我们正在研究URL资源。其中属性文件直接从SVN读取。除了属性文件之外,不需要更新任何内容。

答案 10 :(得分:0)

我使用Spring开发J2EE应用程序。我在很长一段时间内遇到了同样的问题然后找到了解决方案。  我的问题是在我部署的war文件之外的属性文件中指定数据库属性。我发现的解决方案是使用PropertyPlaceholderConfigurer并指定location属性来定位您的系统位置,

<强>     

这很简单,工作得很好!