【问题标题】:Copying default external configuration on first run of Grails web app在首次运行 Grails Web 应用程序时复制默认外部配置
【发布时间】:2015-10-15 09:57:26
【问题描述】:

在我们的 Grails Web 应用程序中,我们希望使用外部配置文件,这样我们就可以在不发布新版本的情况下更改配置。我们还希望这些文件位于应用程序目录之外,以便它们在持续集成期间保持不变。

我们需要做的最后一件事是确保外部配置文件存在。如果没有,那么我们想创建它们,用预定义的内容(生产环境默认值)填充它们,然后像​​以前一样使用它们。这允许任何管理员在不详细了解实际可用选项的情况下更改应用程序的设置。

为此,web-app/WEB-INF/conf 中有几个文件可以在应用程序首次运行时复制到外部配置位置。

到目前为止一切顺利。但我们需要在初始化应用程序之前执行此操作,以便将与生产相关的数据源定义修改考虑在内。

我可以在Config.groovy文件内进行复制和加载操作,但我目前不知道WEB-INF/conf目录的绝对位置。

如何在初始化的早期阶段获取位置?有没有其他办法解决这个问题?

【问题讨论】:

    标签: grails configuration external web-inf


    【解决方案1】:

    有一个最佳实践。

    一般情况下,切勿写入部署应用程序的文件夹。你无法控制它。下一次发布将删除您在那里编写的所有内容。

    相反,利用真正专业人士使用的内置配置功能(Spring 和/或 JPA)。

    JNDI 是查找数据库、文件和 URL 等资源的标准。

    操作将不得不配置 JNDI,但他们感谢关注。

    他们还需要一组初始配置文件,并随时准备根据开发团队的要求进行更改。

    与往常一样,所有配置文件都应该在您的源代码仓库中。

    【讨论】:

      【解决方案2】:

      我终于通过使用 Java 定位放置在类路径上的资源的能力自己解决了这个问题。

      我稍后将 .groovy 文件复制到外部,将它们放入 grails-app/conf 目录(位于类路径中)并在其名称后附加一个后缀,以便在打包应用程序时不会编译它们.所以现在我有 *Config.groovy 包含配置默认值(适用于所有环境)的文件和 *Config.groovy.production 包含生产环境默认值的文件(覆盖预编译的默认值)。

      现在 - Config.groovy 是这样开始的:

      grails.config.defaults.locations = [ EmailConfig, AccessConfig, LogConfig, SecurityConfig ]
      
      environments {
          production {
              grails.config.locations = ConfigUtils.getExternalConfigFiles(
                  '.production',
                  "${userHome}${File.separator}.config${File.separator}${appName}",
                  'AccessConfig.groovy',
                  'Config.groovy',
                  'DataSource.groovy',
                  'EmailConfig.groovy',
                  'LogConfig.groovy',
                  'SecurityConfig.groovy'
              )
          }
      }
      

      然后是ConfigUtils 类:

      public class ConfigUtils {
      
          // Log4j may not be initialized yet 
          private static final Logger LOG = Logger.getGlobal()
      
          public static def getExternalConfigFiles(final String defaultSuffix, final String externalConfigFilesLocation, final String... externalConfigFiles) {
      
              final def externalConfigFilesDir = new File(externalConfigFilesLocation)
      
              LOG.info "Loading configuration from ${externalConfigFilesDir}"
      
              if (!externalConfigFilesDir.exists()) {
                  LOG.warning "${externalConfigFilesDir} not found. Creating..."
                  try {
                      externalConfigFilesDir.mkdirs()
                  } catch (e) {
                      LOG.severe "Failed to create external configuration storage. Default configuration will be used."
                      e.printStackTrace()
                      return []
                  }
              }
      
              final def cl = ConfigUtils.class.getClassLoader()
              def result = []
      
              externalConfigFiles.each {
      
                  final def file = new File(externalConfigFilesDir, it)
                  if (file.exists()) {
                      result << file.toURI().toURL()
                      return
                  }
      
                  final def error = false
                  final def defaultFileURL = cl.getResource(it + defaultSuffix)
                  final def defaultFile
      
                  if (defaultFileURL) {
                      defaultFile = new File(defaultFileURL.toURI())
                      error = !defaultFile.exists();
                  } else {
                      error = true
                  }
      
                  if (error) {
                      LOG.severe "Neither of ${file} or ${defaultFile} exists. Skipping..."
                      return
                  }
      
                  LOG.warning "${file} does not exist. Copying ${defaultFile} -> ${file}..."
      
                  try {
                      FileUtils.copyFile(defaultFile, file)
                  } catch (e) {
                      LOG.severe "Couldn't copy ${defaultFile} -> ${file}. Skipping..."
                      e.printStackTrace()
                      return
                  }
      
                  result << file.toURI().toURL()
              }
      
              return result
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多