如何在运行时更改Spring的@Scheduled fixedDelay

我需要以固定的间隔运行批处理作业,并且能够在运行时更改此批处理作业的时间。 为此,我遇到了Spring框架下提供的@Scheduled注释。 但我不确定如何在运行时更改fixedDelay的值。 我做了一些谷歌搜索但没有找到任何有用的东西。

您可以使用Trigger动态设置下一个执行时间。 在这里看到我的答案:

以编程方式使用Spring调度作业(动态设置fixedRate)

在spring boot中,您可以直接使用应用程序属性!

例如:

 @Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds}000") private void process() { // your impl here } 

请注意,如果未定义属性,您也可以使用默认值,例如,默认值为“60”(秒):

 @Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds:60}000") 

我发现的其他事情:

  • 该方法必须无效
  • 该方法必须没有参数
  • 该方法可能是private

我发现能够使用private可见性并以这种方式使用它:

 @Service public class MyService { public void process() { // do something } @Scheduled(fixedDelayString = "${my.poll.fixed.delay.seconds}000") private void autoProcess() { process(); } } 

作为private ,预定的方法可以是您的服​​务的本地方法,而不是您的服务的API的一部分。

此外,此方法允许process()方法返回一个@Scheduled方法可能不会返回的值。 例如,您的process()方法可能如下所示:

 public ProcessResult process() { // do something and collect information about what was done return processResult; } 

提供有关处理过程中发生的事情的一些信息。

创建接口,类似于:

  public abstract class DynamicSchedule{ /** * Delays scheduler * @param milliseconds - the time to delay scheduler. */ abstract void delay(Long milliseconds); /** * Decreases delay period * @param milliseconds - the time to decrease delay period. */ abstract void decreaseDelayInterval(Long milliseconds); /** * Increases delay period * @param milliseconds - the time to increase dela period */ abstract void increaseDelayInterval(Long milliseconds); } 

接下来,让我们在spring-context项目中实现位于org.springframework.scheduling的Trigger接口。

 import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.TriggerContext; import java.util.Date; import java.util.concurrent.ScheduledFuture; public class CustomDynamicSchedule extends DynamicSchedule implements Trigger { private TaskScheduler taskScheduler; private ScheduledFuture schedulerFuture; /** * milliseconds */ private long delayInterval; public CustomDynamicSchedule(TaskScheduler taskScheduler) { this.taskScheduler = taskScheduler; } @Override public void increaseDelayInterval(Long delay) { if (schedulerFuture != null) { schedulerFuture.cancel(true); } this.delayInterval += delay; schedulerFuture = taskScheduler.schedule(() -> { }, this); } @Override public void decreaseDelayInterval(Long delay) { if (schedulerFuture != null) { schedulerFuture.cancel(true); } this.delayInterval += delay; schedulerFuture = taskScheduler.schedule(() -> { }, this); } @Override public void delay(Long delay) { if (schedulerFuture != null) { schedulerFuture.cancel(true); } this.delayInterval = delay; schedulerFuture = taskScheduler.schedule(() -> { }, this); } @Override public Date nextExecutionTime(TriggerContext triggerContext) { Date lastTime = triggerContext.lastActualExecutionTime(); return (lastTime == null) ? new Date() : new Date(lastTime.getTime() + delayInterval); } } 

现在配置:

 @Configuration public class DynamicSchedulerConfig { @Bean public CustomDynamicSchedule getDinamicScheduler() { ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.initialize(); return new CustomDynamicSchedule(threadPoolTaskScheduler); } } 

和用法:

 @EnableScheduling @Component public class TestSchedulerComponent { @Autowired private CustomDynamicSchedule dynamicSchedule; @Scheduled(fixedDelay = 5000) public void testMethod() { dynamicSchedule.delay(1000l); dynamicSchedule.increaseDelayInterval(9000l); dynamicSchedule.decreaseDelayInterval(5000l); } } 

AFAIK Spring API不允许您访问更改触发器所需的内部。 但您可以手动配置bean:

             

然后如SchedulerFactoryBean中所述:

要在运行时动态注册作业,请使用对此SchedulerFactoryBean的bean引用来直接访问Quartz Scheduler( org.quartz.Scheduler )。 这允许您创建新的作业和触发器,以及控制和监视整个调度程序。