我有一个Spring-Boot应用程序,它将成为我们要触发的其他几个流程的编排服务。我目前使用Spring Scheduling设置它,以动态地从数据库中提取cron。我使用了rest方法来触发从数据库中提取新的cron信息的过程。此逻辑全部正常工作。唯一的“问题”是,它直到下一个计划运行才使用真正的问题才使用新的cron信息。 有没有一种方法可以中断当前的触发器,并使用更新的cron信息再次安排。 这是供参考的应用程序:
package com.bts.poc; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.TriggerContext; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.support.CronTrigger; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.Date; @SpringBootApplication @EnableScheduling @RestController @RequestMapping("/APSCommon/Scheduling") public class Application implements SchedulingConfigurer { @Autowired private DynamicCron dynamicCron; @Autowired PropertyManager propertyManager; public static void main(String[] args) throws Exception { SpringApplication.run(Application.class); } private String cronConfig() { String cronTabExpression = propertyManager.getProperty("COMPANY", "JOB_NAME","CRON_EXPRESSION"); return cronTabExpression; } @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addTriggerTask(new Runnable() { @Override public void run() { dynamicCron.runJob(); } }, new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) { String cron = cronConfig(); CronTrigger trigger = new CronTrigger(cron); Date nextExec = trigger.nextExecutionTime(triggerContext); DynamicCron.cronExpression = cron; return nextExec; } }); } @RequestMapping(value = "/reloadScheduling", method = RequestMethod.GET) public String reloadScheduling() { PropertyManager.setResetProperties(true); return "schedules will be altered next run"; } }
因此,使用SchedulingConfigurer-> configureTasks时,您无法访问我正在使用的Spring版本(4.2.7.RELEASE)中的ScheduledFuture。从我读过的几篇文章中,已经提到它是将来可能的功能。我通过执行以下操作解决了这个问题:
package com.bts.poc; import com.bts.poc.service.DynamicCron; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; import java.util.TimeZone; import java.util.concurrent.ScheduledFuture; @SpringBootApplication(exclude = MessageSourceAutoConfiguration.class) @EnableScheduling @RestController public class Application extends SpringBootServletInitializer { @Autowired private DynamicCron dynamicCron; @Autowired private PropertyManager propertyManager; private static List<ScheduledFuture> scheduledFutures = new ArrayList<>(); private static final Logger LOGGER = LoggerFactory.getLogger(Application.class); private static TaskScheduler scheduler; @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } private String cronConfig() { return propertyManager.getProperty("COMPANY", "JOB_NAME", "CRON_EXPRESSION"); } @RequestMapping(value = {"scheduling/start"}, method = RequestMethod.GET) public @ResponseBody String startScheduling() { scheduleAll(); LOGGER.info("Scheduling of jobs has been started."); return "Scheduling of jobs has been started."; } @RequestMapping(value = {"scheduling/cancel"}, method = RequestMethod.GET) public @ResponseBody String cancelScheduling() { cancelAll(); LOGGER.info("Cancelling all scheduled jobs."); return "Cancelling all scheduled jobs."; } private void scheduleAll() { LOGGER.info("Scheduling all applications to run."); cancelAll(); //eventually go through the database and load all jobs to be scheduled here. schedule(cronConfig()); } /** * Cancel all the scheduled reports */ private void cancelAll() { for (ScheduledFuture scheduledFuture : scheduledFutures) { scheduledFuture.cancel(true); } scheduledFutures.clear(); } /** * Schedule the scheduled report with the given cron schedule information */ private void schedule(String cronSchedule) { TimeZone tz = TimeZone.getDefault(); LOGGER.info("Setting up application {} to execute with cron string: '{}'.", cronSchedule); CronTrigger trigger = new CronTrigger(cronSchedule, tz); scheduler = scheduler(); if (scheduler == null) { LOGGER.error("Unable to schedule job as scheduler was not found"); return; } ScheduledFuture<?> future = scheduler.schedule(new DynamicCron(), trigger); scheduledFutures.add(future); } @Bean public TaskScheduler scheduler() { if (scheduler == null) { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.afterPropertiesSet(); } return scheduler; } }
这基本上复制了ScheduledTaskRegistrar提供的功能,使您可以管理ScheduledFuture。希望这可以在将来对其他人有所帮助。