【问题标题】:Tomcat 6 / 7 - how to override a properties file within a Web Application?Tomcat 6 / 7 - 如何覆盖 Web 应用程序中的属性文件?
【发布时间】:2013-10-03 02:38:28
【问题描述】:

我继承了 Web 应用程序的责任,而它管理属性文件的方式似乎是错误的。属性文件在 WAR 文件中提供并位于目录中:

<tomcat>/webapps/<my web app>/WEB-INF/classes

对于我们的 Web 应用程序的首次安装者来说,这很好。默认属性文件有许多默认设置,以这种方式指定默认值似乎比将值硬编码到 Java 代码中更好。

此文件仅在 Tomcat 启动时读取,但可以随时由正在运行的 Web 应用程序更新。

当客户需要升级软件时,他们必须执行以下步骤

  1. 停止 tomcat 以停止 Web 应用程序。
  2. 复制文件:foo.properties
  3. 删除现有的 Web 应用程序目录
  4. 部署新的war文件(纯粹是为了解压)
  5. 停止 tomcat(再次!)
  6. 将旧的 foo.properties 复制到新的(在 WEB-INF/classes 中)
  7. 重启tomcat。

这似乎冗长且容易出错 - 我们经常让用户意外擦除他们的属性文件。属性文件肯定应该以某种方式外部化吗?我喜欢包含默认值的 WAR 文件的想法,但是如果在类路径中找到另一个名为 foo.properties 的文件,是否有办法覆盖这些值?我真的希望新的部署是:

  1. 停止 Web 应用程序
  2. 部署新的 Web 应用程序

它会从外部位置获取属性。

Tomcat 是否提供了执行此操作的任何技术,或者我是否应该简单地更改 Java 代码以在其他地方查找属性文件(例如用户的主目录)?

在写这个问题时,我遇到了对 conf/catalina.properties 的引用,以及如何使用它来指定将在 WEB-INF/classes 之前读取的目录。但是修改 common.loader 和 shared.loader 似乎完全没有效果!我从:http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html 获得此信息。

非常感谢任何建议。

更新 属性文件正在通过 Spring 加载。 bean 文件有以下内容:

<value>classpath:foo.properties</value>

现在我可以更改使用此属性文件的 bean 的实例化方式,并具有不同的属性文件加载机制。但是由于 Spring 只是查看类路径以获取 foo.properties,因此将客户属性文件简单地放在类路径上似乎是合乎逻辑的。

【问题讨论】:

    标签: spring tomcat web-applications properties startup


    【解决方案1】:

    如果我是您的客户,我也不会喜欢您当前的升级机制。我喜欢将属性分配给默认值的想法,但如果客户愿意,他们可以覆盖它们。这是实现它的一种方法。有两个属性文件 default.properties 和 external.properties。 default.properties 具有默认值,而另一个是空的,可供客户使用。客户根本不会触及 default.properties。您可以在 /webapps//WEB-INF/classes 中保留 default.properties 的位置。另一个属性文件可以在任何地方,您可以使用系统属性指定它。假设你决定把它放在

     /home/customer/external.properties
    

    现在更改您的 java 代码,使其加载 default.properties,然后加载 external.properties。如果在两个文件中都定义了一个属性,则首选 external.properties 中的属性。在文件中

    $TOMCAT_HOME/bin/setenv.sh
    

    声明如下环境变量

    export JAVA_OPTS="-Dexternal.props=/home/customer/external.properties"
    

    如果您在 Windows 上,则在 setenv.bat 中声明环境变量。现在您应该可以通过

    访问 external.properties 文件了
    Properties properties = new Properties();
    try {
          properties.load(new FileInputStream(System.getProperty("external.props")));
     } catch (IOException e) {
      ...
    }
    

    【讨论】:

    • 一个好主意。但是,我在原始帖子中解释的问题稍微复杂一些。 Spring 以下列方式加载属性: classpath:foo.properties 。所以这就是为什么我正在考虑覆盖类路径。我会更新原来的问题
    • @Phil 我读了你的更新。我不得不不同意客户编辑的东西应该在类路径中。对我来说,您提供的属性文件需要在类路径中,并且外部属性文件可以根据其所在位置进行配置。您可以使用 'classpath:' 和 'file:' 指令在 Spring beans.xml 中列出所需的属性文件。不要引用我的话,但我认为在春季列出属性文件的顺序对于被覆盖的内容很重要。
    • @TheGovernor 订单确实很重要。它基本上是内部地图,文件按从上到下的顺序加载。所以最后一个文件有机会覆盖所有前面的值。
    猜你喜欢
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    相关资源
    最近更新 更多