问题是:我该如何处理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
不幸的是,这不是我想要的!
我发现了两种解决方法:
第一个,纯粹基于Spring表达式。如果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表达式语言可以处理多个后备。是应该使用它,还是更易读的配置方法...我让您决定。