我喜欢@Scheduled使用.yml文件的不同配置属性来实现一项作业。
@Scheduled
.yml
在我的yaml文件中,我将其描述cron expression为列表:
cron expression
job: schedules: - 10 * * * * * - 20 * * * * *
我使用Configuration读取了这些值,并创建了一个@Beannamed scheduled:
@Bean
scheduled
@Configuration @ConfigurationProperties(prefix="job", locations = "classpath:cronjob.yml") public class CronConfig { private List<String> schedules; @Bean public List<String> schedules() { return this.schedules; } public List<String> getSchedules() { return schedules; } public void setSchedules(List<String> schedules) { this.schedules = schedules; } }
在我的Job类中,我想开始执行一种方法,但是要执行配置中的两个计划。
@Scheduled(cron = "#{@schedules}") public String execute() { System.out.println(converterService.test()); return "success"; }
使用此解决方案,应用程序将创建错误:(或多或少清晰)
Encountered invalid @Scheduled method 'execute': Cron expression must consist of 6 fields (found 12 in "[10 * * * * *, 20 * * * * *]")
是否可以使用多个cron表达式声明来配置相同的计划作业方法?
编辑1
经过一番尝试后,我只是在executer方法上使用了第二个注释。
@Scheduled(cron = "#{@schedules[0]}") @Scheduled(cron = "#{@schedules[1]}") public String execute() { System.out.println(converterService.test()); return "success"; }
此解决方案有效,但并非真正动态。有没有办法使它动态?
(编辑,因为我找到了一种执行此操作的方法)
您实际上可以做到这一点。下面我展示了一个工作示例:
cronjob.yaml
执行 MyTask 的实际任务:
package hello; import org.springframework.stereotype.Component; @Component public class MyTask implements Runnable { @Override public void run() { //complicated stuff } }
您的 CronConfig 如下:
package hello; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; @Configuration @ConfigurationProperties(prefix="job", locations = "classpath:cronjob.yml") public class CronConfig { private List<String> schedules; @Bean public List<String> schedules() { return this.schedules; } public List<String> getSchedules() { return schedules; } public void setSchedules(List<String> schedules) { this.schedules = schedules; } }
该 ScheduledTask 豆,负责安排所有crons:
package hello; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; @Component public class ScheduledTasks { @Autowired private TaskScheduler taskScheduler; @Autowired private CronConfig cronConfig; @Autowired private MyTask myTask; private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class); public void scheduleAllCrons() { cronConfig.getSchedules().forEach( cron -> taskScheduler.schedule(myTask, new CronTrigger(cron)) ); } }
上下文/主类 应用程序 :
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; @SpringBootApplication @EnableScheduling @EnableAsync public class Application { @Bean public TaskScheduler taskScheduler() { return new ConcurrentTaskScheduler(); } public static void main(String[] args) throws Exception { ApplicationContext ctx = SpringApplication.run(Application.class); ScheduledTasks scheduledTasks = ctx.getBean(ScheduledTasks.class); scheduledTasks.scheduleAllCrons(); } }