如何在 Grails 3 中使用外部 .groovy 配置文件

Posted

技术标签:

【中文标题】如何在 Grails 3 中使用外部 .groovy 配置文件【英文标题】:How to use external .groovy config file in Grails 3 【发布时间】:2016-12-03 08:33:25 【问题描述】:

Externalized Configuration 中的第 24.3 节表示 .properties.yml 文件可用于外部配置,但我希望我的外部配置是 .groovy 文件,就像我拥有的​​ application.groovy 文件一样已从.yml 转换。我怎样才能做到这一点?

Grails 版本 3.2.0.M2

更新:

我能够根据@Michal_Szulc 提供的答案完成这项工作

请注意,ConfigSlurper 需要当前环境才能正常工作。另请注意,这些更改将针对my_grails_app/grails-app/init/my_grails_app/Application.groovy 文件进行,而不是my_grails_app/grails-app/conf/application.groovy 文件,如果您从.yml 配置转换为.groovy 配置,您可能拥有的文件。

package my_grails_app

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.context.EnvironmentAware
import org.springframework.core.env.Environment
import org.springframework.core.env.MapPropertySource

class Application extends GrailsAutoConfiguration implements EnvironmentAware 
    static void main( String[] args ) 
        GrailsApp.run( Application, args )
    

    @Override
    void setEnvironment( Environment environment ) 
        def appName = grails.util.Metadata.current.getApplicationName()

        // The value of this environment variable should be the absolute path to an external .groovy config file like /opt/my_grails_app/my_grails_app-config.groovy.
        def envVarName = "MY_GRAILS_APP_CONFIG"

        // If you don't want to use an environment variable you can specify your external .groovy config file here, but the environment variable will still be checked first.
        def dfltAppConfigFileName = "/opt/$ appName /$ appName -config.groovy"
        def appConfigFile = null
        def loadDfltConfig = false

        // Try to load config specified by the environment variable first
        println "Checking the environment variable $ envVarName  for the configuration file location..."
        def envVarVal = System.getenv( envVarName ) ?: System.getProperty( envVarName )
        if( envVarVal ) 
            appConfigFile = new File( envVarVal )
            if( !appConfigFile.exists() ) 
                println "The configuration file $ appConfigFile  specified by the environment variable $ envVarName  does not exist.  Checking for the default configuration file $ dfltAppConfigFileName  instead..."
                appConfigFile = null
                loadDfltConfig = true
            
         else 
            println "The environment variable $ envVarName  which specifies the configuration file to be loaded does not exist.  Checking for the default configuration file $ dfltAppConfigFileName  instead..."
            appConfigFile = null
            loadDfltConfig = true
        

        // Try loading the default config file since we couldn't find one specified by the environment variable
        if( loadDfltConfig ) 
            appConfigFile = new File( dfltAppConfigFileName )
            if( !appConfigFile.exists() ) 
                println "The default configuration file $ dfltAppConfigFileName  does not exist."
                appConfigFile = null
            
        

        // Load the config file if it exists, otherwise exit
        if( appConfigFile ) 
            println "Loading configuration file $ appConfigFile "
            def config = new ConfigSlurper( environment.activeProfiles.first() ).parse( appConfigFile.toURI().toURL() )
            environment.propertySources.addFirst( new MapPropertySource( "$ appName -config", config ) )
         else 
            println "No configuration file found.  Exiting."
            System.exit( 1 )
        

【问题讨论】:

【参考方案1】:

我找到了this thread 和 Graeme Rocher 的引用:

Grails 3 使用 Spring 的属性源概念,所以它会解决 来自系统、环境和最后的属性 application.yml/application.groovy

Clyde Balneaves的代码:

class Application extends GrailsAutoConfiguration implements EnvironmentAware 
    static void main(String[] args) 
    GrailsApp.run(Application)
    

    @Override
    void setEnvironment(Environment environment) 
    //Set up Configuration directory
    def krakenHome = System.getenv('KRAKEN_HOME') ?: System.getProperty('KRAKEN_HOME') ?: "/opt/kraken"

    println ""
    println "Loading configuration from $krakenHome"
    def appConfigured = new File(krakenHome, 'KrakenConfig.groovy').exists()
    println "Loading configuration file $new File(krakenHome, 'KrakenConfig.groovy')"
    println "Config file found : " + appConfigured

    if (appConfigured) 
        def config = new ConfigSlurper().parse(new File(krakenHome, 'KrakenConfig.groovy').toURL())
        environment.propertySources.addFirst(new MapPropertySource("KrakenConfig", config))
    
    

【讨论】:

谢谢,这让我走上了正确的道路。我必须进行一些更改,我在更新我的问题时注意到了这些更改。 谢谢 Michal_Szulc :这有助于我读取外部 Application.groovy 文件,但如果 application.yml 文件中存在相同的配置,则外部文件配置不适用。你能帮我解决这个问题吗? 我认为它是故意的 - 恕我直言 application.yml 应该比其他配置文件更受青睐。【参考方案2】:

也许你也可以尝试这种方式(覆盖运行方法)

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import grails.util.Environment
import grails.util.Holders
import org.springframework.boot.CommandLineRunner

class Application extends GrailsAutoConfiguration implements CommandLineRunner 

    static void main(String[] args) 
        GrailsApp.run(Application, args)
    

    @Override
    void run(final String... args) throws Exception 
        println "Running in $Environment.current.name"

        // Get configuration from Holders.
        def config = Holders.getConfig()
        def locations = config.grails.config.locations
        locations.each 
            String configFileName = it.split("file:")[1]
            File configFile = new File(configFileName)
            if (configFile.exists()) 
                config.merge(new ConfigSlurper(Environment.current.name).parse(configFile.text))
            
        
    

【讨论】:

在给出答案时,最好解释一下为什么你的答案是这个答案。 我做到了。我说可能你也可以尝试其他方式。这只是我发现的另一种解决方案 您的回答没有解释为什么您认为这是答案。它只是表明它可能值得一试。请记住,Stack Overflow 的目的是提出答案,以便其他人在未来使用它们。如果您不解释为什么您的答案有效,那么它对接下来出现的人来说不会很有用。 我说你也可以试试这个方法。并且我提供的解决方案在我的电脑上为我工作,这就是我在此处粘贴此解决方案的原因。我认为堆栈溢出具有相同的点赞和反对票(判断解决方案是否有效)。【参考方案3】:

我认为您正在寻找的(并且更容易/更清洁)是Grails External Config plugin。

【讨论】:

以上是关于如何在 Grails 3 中使用外部 .groovy 配置文件的主要内容,如果未能解决你的问题,请参考以下文章

如何从grails 3.1.8中的外部文件加载数据源配置?

如何在 Grails 2.4 中外部化 Maven 凭证

访问被拒绝并获取 抱歉,在 grails 中将插件 Spring Security 核心升级到 2.0 版本后,您无权查看此页面

如何从 Grails 控制器和视图外部引用 Grails 域类字段?

从 Grails 应用程序外部插入数据时,Grails 如何设置 _idx 字段?

使用RabbitMQ插件在Grails中创建队列运行时