首页 > 解决方案 > 如何在 Spring 表达式语言中处理多个后备值

问题描述

问题是:如何处理 Spring 表达式中的一串后备值,允许我在获得定义值之前回退到更高级别的配置?

为了稍微解释一下,让我们用我自己的用例来说明这一点:我打算使用@Scheduled注释创建一个 Spring 应用程序来运行一些进程。事情是我有很多计划任务,我会让运行频率可以轻松地为所有这些任务配置,或者只为一个子集配置。

所以我一直在寻找类似的东西

@Component
public class SpecificTaskRunner {

   @Scheduled(cron = "${ specific-task-cron ?: task-families-cron ?: default-cron }")
   public void specificTask() {
      doSomething();
   }

}

让应用程序通过覆盖值一次配置所有计划任务的频率default-cron,或者通过覆盖任务族属性仅配置其中的一个子集,或者最后在任务的基础上进行指定。这种方法的优点是它允许使用多个配置级别,因为每个计划任务从最具体的开始寻找适当的属性,并寻找更通用的属性直到它得到定义,最终回退到默认的全局值.

不幸的是......这不起作用。评估时,如果未定义第一个元素,则如果回退整个剩余元素。在此示例中,这意味着如果配置缺少 的值specific-task-cron,则解析的值是 :task-families-cron ?: default-cron不幸的是,这不是我想要的!

标签: javaspringspring-el

解决方案


我找到了两种处理方法:

第一个,纯粹是基于Spring的表达方式。如果它也是一个 Spring 表达式,那么 Spring 似乎会重新评估 Elvis 运算符的结果。所以我的工作配置是:

@Component
public class SpecificTaskRunner {

   @Scheduled(cron = "${ specific-task-cron ?: ${ task-families-cron ?: default-cron }}")
   public void specificTask() {
      doSomething();
   }

}

在我的实际用例中,再加上一个后备,并不是很方便......

所以我切换到一个更简单的解决方案,它通过这种方式定义一个值链来依赖配置:

#application.yml

default-cron: '0 */5 0 0 0 0' #every 5 minutes
task-families-cron: ${default-cron}
specific-task-cron: ${task-families-cron}

结合

@Component
public class SpecificTaskRunner {

   @Scheduled(cron = "${specific-task-cron}")
   public void specificTask() {
      doSomething();
   }

}

这样,任何对属性的覆盖都适用于分层子级别,除非它们自己被覆盖。

这两种解决方案似乎都有效,所以最后,是的 Spring 表达式语言处理多个回退。是否应该使用,或者配置方法更具可读性......我让你决定。


推荐阅读