【问题标题】:Spring Boot: using SpEL collection selection from YAML in @ConditionalOnExpressionSpring Boot:在@ConditionalOnExpression 中使用 YAML 中的 SpEL 集合选择
【发布时间】:2022-09-27 20:53:22
【问题描述】:

我有一个带有 YAML 配置的 Spring Boot 应用程序,其中包含如下功能列表:

features:
  - key: feature1
    enabled: true
    description: First feature
  - key: feature2
    enabled: false
    description: Second feature
...

我想使用@ConditionalOnExpression 有条件地初始化与这些功能相关的bean,通过键识别它们。由于 \"features\" 属性是一个列表,看来我需要选择集合来执行此操作。我已经为注释的值尝试了这两个选项:

@ConditionalOnExpression(\"${features.?[key == \'feature1\'][0].enabled}\")

@ConditionalOnExpression(\"${features}.?[key == \'feature1\'][0].enabled\")

但两者都在启动时给出相同的错误:

org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: \'lcurly({)\'

如果我将表达式(不带 ${})传递给 SpelExpressionParser.parseExpression() 然后评估它(针对以编程方式构建的特征对象列表),它会按预期工作并返回 \"enabled\" 属性的值。所以表达式的结构似乎还可以,问题是我如何在@ConditionalOnExpression 中使用它。我到底做错了什么?

    标签: java spring spring-boot spring-el


    【解决方案1】:

    ${...}与SpEL无关;该语法适用于 Spring 中的属性占位符。

    例如@Value("${property.foo:default}" String someProperty

    这会将someProperty 设置为property.foo(如果存在)的值,否则设置default。 (:... 部分可以省略以强制属性存在)。

    【讨论】:

    • 明白了,谢谢解释
    【解决方案2】:

    Spring SpEL 仅支持属性文件中的简单属性占位符。

    如果您的属性文件和条件代码是这样的,您的 SpEL 将起作用:

    features:
      feature1:
        enabled: true
        description: First feature.
      feature2:
        enabled: false
        description: Second feature.
    
    @ConditionalOnExpression(
            value = "#{'${features.feature1.enabled}'.equals('true')}"
    )
    
    但是如果你想把它加载为地图特征并使用地图SpEL特征;

    最优雅的方法是编写 key-values as an inline JSON(使用 ' 和 " 字符以避免繁琐的转义)并使用 SpEL 解析它:

    features: '{
    "feature1": {"enabled":"true", "description":"..."},
    "feature2": {"enabled":"false", "description":"..."}
    }'
    
    @ConditionalOnExpression(
            value = "#{${features}['feature1']['enabled'].equals('true')}"
    )
    

    如果您使用了选择方法,它会看起来像这样;

    @ConditionalOnExpression(
            value = "#{${features}.?[key=='feature1']['feature1']['enabled'].equals('true')}"
    )
    

    【讨论】:

    • 所以从列表中选择集合不应该在条件中使用,对吧?
    • collection selection 没有这样的限制。限制你的部分;事实上,您无法直接从 SpEL 中的 YAML 文件获取复杂的列表/映射。
    猜你喜欢
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多