【问题标题】:How to create ConfigObject using only nested maps in Grails?如何仅使用 Grails 中的嵌套映射创建 ConfigObject?
【发布时间】:2014-09-28 04:00:01
【问题描述】:

是否可以将基于闭包的配置实现为地图的地图?

grails {
  acme {
     host = 'localhost'
     poolSettings {
        timeout = 5000
     }
  }
}

以上配置是 grails 插件的约定。我们正在进行迁移,由于遗留限制,我们需要动态创建配置以消除对遗留代码的影响。

我从一个简单的配置开始:

grails.acme = [host:'localhost']

这个插件在启动时可以正常工作,所以我添加了一个嵌套地图:

grails.acme = [host:'localhost']
def poolProps = //do some work to get pool settings
grails.acme << [poolSettings:poolProps]

在启动时我会打印grails.acme:

{
    "host": "locahost",
    "poolSettings": {
        "timeout": 5000
    }
}

看起来很正常,但是在 acme 插件失败后不久出现以下错误:

2014-09-27 23:27:07,460 [localhost-startStop-1] 错误 context.GrailsContextLoader - 初始化应用程序时出错:否 方法签名:AcmePlugin$_closure2_closure5_closure9 .doCall() 适用于参数类型:(grails.spring.BeanBuilder) 值: [grails.spring.BeanBuilder@7b067fd7] 可能的解决方案: doCall(java.lang.Object, java.lang.Object), call(), 调用([Ljava.lang.Object;),调用(java.lang.Object), 调用(java.lang.Object,java.lang.Object),findAll()消息:否 方法签名: AcmeGrailsPlugin$_closure2_closure5_closure9.doCall() 适用 对于参数类型:(grails.spring.BeanBuilder)值: [grails.spring.BeanBuilder@7b067 fd7] 可能的解决方案: doCall(java.lang.Object, java.lang.Object), call(), 调用([Ljava.lang.Object;),调用(java.lang.Object), 调用(java.lang.Object, java.lang.Object)

我对此感到有些困惑,我认为这是不可能的,而且我什至不确定如何动态处理基于闭包的约定。

【问题讨论】:

    标签: grails groovy dsl spring-dsl


    【解决方案1】:

    您的代码的一个问题可能是配置节点结构看起来完全正常,但实际上并非如此。 IE。有些节点是Map 实例,但不是ConfigObject 实例。

    在大多数情况下,这可能无关紧要,但在您的情况下,第 3 方插件似乎因一些丑陋且难以理解的异常而失败。

    我无法重现您的问题,因此我无法确定这是否是您遇到的真正问题,也无法确定建议的解决方案是否能解决您的问题。尽管如此,我的第一次尝试是修复类型,以便配置树中的所有节点都是ConfigObject 类型。像这样的:

    def poolProps = [timeout: 5000] as ConfigObject // convert type to ConfigObject
    grails.acme.host = 'localhost'
    grails.acme << [ poolSettings : poolProps ]
    

    请注意,如果您创建的地图(在本例中为 poolProps)包含嵌套的地图元素,您也必须转换这些元素。

    【讨论】:

    • 我在 grails redis 插件 1.5.5 上尝试了这个,如果你想尝试复制,用 redis 替换 acme,大声笑,我会试试你的建议,我
    • 我创建了一个类似的答案只是为了清楚 Grails 不是必需的。感谢@Steiner:stackoverflow.com/questions/39497150/…
    【解决方案2】:

    是的,实际上是有可能的

    grails {
       acme {
          host = 'localhost'
          poolSettings {
             timeout = 5000
          }
       }
    }
    

    等同于:

    grails.acme.host = 'localhost'
    grails.acme.poolSettings.timeout = 5000
    

    闭包只是语法糖。您甚至可以将这两种类型结合起来:

    grails.acme {
       host = 'localhost'
       poolSettings.timeout = 5000
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 2018-09-15
      • 2023-03-22
      相关资源
      最近更新 更多