【问题标题】:Configuration Management in JavaEEJavaEE 中的配置管理
【发布时间】:2012-10-11 08:34:42
【问题描述】:

我的目标

我有一个 JavaEE 环境(在我的特定情况下是 Glassfish Web Profile),我想要一种独立于容器的方式来配置我的应用程序,并具有以下功能:

  1. 未指定其他内容时的默认配置(在 WAR 文件中)
  2. 自定义配置(WAR 文件外)分为两层:
    • 主机特定设置(在外部属性文件中;例如某个工作目录)
    • 应用程序特定设置(在数据库中;例如邮箱大小)

我希望部署和运行我的应用程序(设置 JNDI 数据源,部署 WAR 文件,在某些配置中具有可选的 .properties 文件)的前提条件尽可能少(现在唯一的一个是 JNDI 数据源)文件夹和 - 完成)。

这引出了我的第一个问题: 这是一种常见/良好/有用的设置,还是不必要的复杂和/或非常奇特?

我的想法(到目前为止)

默认配置

默认配置将在属性文件中:

src/main/resources/config/default.properties

应用程序范围的 bean 在初始化时读取此属性,如 here 所述:

@Named
@ApplicationScoped
public class Configuration implements Serializable {

    ...

    @PostConstruct
    public void initConfiguration() {
        loadDefaultConfiguration();
    }

    private void loadDefaultConfiguration() {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        try (InputStream input = classLoader.getResourceAsStream("/config/default.properties")) {
            properties.load(input);
        } catch(IOException ex) {
            LOGGER.error(...);
        }
    }

}

应用程序特定设置

这些设置将存储在包含键和值列的数据库表中。它们将始终通过 EntityManager 访问,希望 JPA 实现的缓存会很聪明:)。这样做的好处是,这些设置可以在应用程序运行时轻松更改。

@Named
@ApplicationScoped
public class Configuration implements Serializable {

    ...

    public T getProperty(final PropertyKeyEnum key, final Class<T> type) {
        if (key.getSource() == PropertySourceEnum.DATABASE) {
            return configurationDao.getByKey(key.getKey(), type);
        }

        ...
    }
}

主机特定设置

最后,这是我的主要问题

如何以独立于容器的方式访问外部属性文件?用户只需将myAppName.properties 文件放入容器的默认配置文件夹,应用程序就可以找到并加载该文件(至少在应用程序启动时)。

我的环境

  • JavaSE 7
  • JavaEE 6
  • Glassfish 3.1.2 Web(但这不重要;))

更新

我在 Glassfish 的管理区域找到了一个位置,您可以在其中指定一些易于访问的系统属性:

System.getProperty("myApp.propertyName");

这可用于存储外部 .properties 文件的路径,但我不确定这是否是一种干净的方式,因为

  1. 不知道是不是每个容器(支持JavaEE)都有这么好的特性
  2. 我真的不想从 Web 应用程序普通访问文件

【问题讨论】:

    标签: java configuration properties java-ee-6 glassfish-3


    【解决方案1】:

    在与我的同事交谈并进行一些研究后,我为主机特定(外部)配置实现了以下内容。

    因为无论如何我的应用程序都需要一个工作目录,所以我决定将此工作目录也用作我的外部配置的位置。因此,我要么使用环境变量(例如MYAPP_HOME),要么如果未设置变量,则使用用户的主文件夹(例如&lt;user.home&gt;/.myapp):

    private Path discoverRootDirectory() {
        String myAppHome = System.getenv("MYAPP_HOME");
    
        if (myAppHome == null) {
            return Paths.get(System.getProperty("user.home"), ".myapp");
        } else {
            return Paths.get(myAppHome);
        }
    }
    

    属性文件将照常加载:

    private void loadConfiguration() {
        properties = new Properties();
        // ...
        try (InputStream inputStream = Files.newInputStream(discoverRootDirectory())) {
            properties.load(inputStream);
        } catch (FileAccessException | IOException ex) {
            // ...
        }
    }
    

    【讨论】:

    • 感谢分享,马库斯!
    【解决方案2】:

    如果您正在尝试创建一种方法来保持您的应用程序可移植,我的猜测是您正在尝试编写一个程序来处理更快速有效的手动处理(由人而不是计算机) .每个容器(Glassfish、JBoss、WebSphere 等)并不局限于必须以与另一个容器相同的方式做事。因此,如果您追求的是可移植性,它们的配置文件可以而且通常会大不相同。最好弄清楚如何在不同的服务器上运行应用程序并保存配置文件。充其量你可以在一个地方做我们所做的事情,并创建带有占位符的文件,这些文件可以与简单的属性文件一起使用,其中脚本替换每个占位符的值(例如端口号等)。您多久在不同类型的服务器之间切换一次?如果你经常说,那么你会遇到比这更多的问题。最好选择一个平台并坚持下去。这样问题就少了很多。

    如果您在这里没有得到您喜欢的答案,请尝试Server Fault(此网站的姐妹网站)。

    【讨论】:

      猜你喜欢
      • 2012-10-08
      • 1970-01-01
      • 2014-03-04
      • 1970-01-01
      • 2011-12-19
      • 2014-06-02
      • 2012-06-18
      • 2015-01-29
      相关资源
      最近更新 更多