Spring 更新调度程序
Spring update scheduler
我在 Spring 有一个预定的工作,我从我的数据库中获取它的 cron。
每执行一次,更新下一次执行时间。因此,如果它配置为每 10 分钟 运行,我可以将值更改为数据库以每 15 分钟安排一次该作业。
问题是我必须等待执行以获取更新的 cron:如果每 15 分钟安排一次作业并且我想将此值更改为每 2 分钟一次,我必须等待下一个执行(最多 15 分钟)以每 2 分钟执行一次此作业。
有没有办法在我更新数据库后重新安排这项工作?
我想销毁并刷新这个 bean,但它不起作用(也许这是不可能的,或者我的实现有问题)。也许有一种方法可以触发事件来执行方法configureTask。
这是我安排的工作的片段。
@EnableScheduling
@Component
public class MyClass implements SchedulingConfigurer {
private static final String JOB = "My personal task";
@Autowired
JobRepository jobRepository;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
}, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB); // read from database
String cron = byJobNameIgnoreCase.getCrontab();
CronTrigger trigger = new CronTrigger(cron);
return trigger.nextExecutionTime(triggerContext);
}
});
}
}
为了管理这个,我创建了一个 SchedulerOrchestrator 来管理我的作业。这些作业包含一个 SchedulerFuture。
这里是我希望可以帮助别人的代码。
让我们从将由我的作业实现的接口开始:
public interface SchedulerObjectInterface {
void start();
void stop();
}
每个作业都需要一个 ScheduledFuture 来停止,并且需要自动装配一个 TaskScheduler 来进行调度。这是一份工作的示例(您可以创建任意数量的工作):
@Component
public class MyFirstJob implements SchedulerObjectInterface {
private static final Logger log = LoggerFactory.getLogger(MyFirstJob.class);
public static final String JOB = "MyFirstJob";
@Autowired
JobRepository jobRepository;
private ScheduledFuture future;
@Autowired
private TaskScheduler scheduler;
@Override
public void start() {
future = scheduler.schedule(new Runnable() {
@Override
public void run() {
System.out.println(JOB + " Hello World! " + new Date());
}
}, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cron = cronConfig();
System.out.println(cron);
CronTrigger trigger = new CronTrigger(cron);
return trigger.nextExecutionTime(triggerContext);
}
});
}
@Override
public void stop() {
future.cancel(false);
}
// retrieve cron from database
private String cronConfig() {
JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB);
return byJobNameIgnoreCase.getCrontab();
}
}
最后我们可以将作业添加到协调器中:
@Configuration
public class SchedulerOrchestrator {
private static final Logger log = LoggerFactory.getLogger(SchedulerOrchestrator.class);
private static Map<String, SchedulerObjectInterface> schduledJobsMap = new HashMap<>();
@Autowired
JobRepository jobRepository;
@Autowired
MyFirstJob myFirstJob;
@Autowired
MySecondJob mySecondJob;
@Autowired
TaskScheduler scheduler;
@PostConstruct
public void initScheduler() {
schduledJobsMap.put(MyFirstJob.JOB, myFirstJob);
schduledJobsMap.put(MySecondJob.JOB, mySecondJob);
startAll();
}
public void restart(String job) {
stop(job);
start(job);
}
public void stop(String job) {
schduledJobsMap.get(job).stop();
}
public void start(String job) {
schduledJobsMap.get(job).start();
}
public void startAll() {
for (SchedulerObjectInterface schedulerObjectInterface : schduledJobsMap.values()) {
schedulerObjectInterface.start();
}
}
@Bean
public TaskScheduler scheduler() {
return new ThreadPoolTaskScheduler();
}
}
考虑这种方法。您可以根据您的观点和 运行 立即检查必要的任务,而不是添加和删除计划任务。这会更容易。检查 Quartz Scheduler,它的 CronExpression 有 isSatisfiedBy(Date date) 方法。
@Scheduled(cron = "5 * * * * *) // do not set seconds to zero, cause it may fit xx:yy:59
public void runTasks() {
LocalTime now = LocalTime.now(); // or Date now = new Date();
// check and run
}
我在 Spring 有一个预定的工作,我从我的数据库中获取它的 cron。 每执行一次,更新下一次执行时间。因此,如果它配置为每 10 分钟 运行,我可以将值更改为数据库以每 15 分钟安排一次该作业。
问题是我必须等待执行以获取更新的 cron:如果每 15 分钟安排一次作业并且我想将此值更改为每 2 分钟一次,我必须等待下一个执行(最多 15 分钟)以每 2 分钟执行一次此作业。
有没有办法在我更新数据库后重新安排这项工作?
我想销毁并刷新这个 bean,但它不起作用(也许这是不可能的,或者我的实现有问题)。也许有一种方法可以触发事件来执行方法configureTask。
这是我安排的工作的片段。
@EnableScheduling
@Component
public class MyClass implements SchedulingConfigurer {
private static final String JOB = "My personal task";
@Autowired
JobRepository jobRepository;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
}, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB); // read from database
String cron = byJobNameIgnoreCase.getCrontab();
CronTrigger trigger = new CronTrigger(cron);
return trigger.nextExecutionTime(triggerContext);
}
});
}
}
为了管理这个,我创建了一个 SchedulerOrchestrator 来管理我的作业。这些作业包含一个 SchedulerFuture。
这里是我希望可以帮助别人的代码。
让我们从将由我的作业实现的接口开始:
public interface SchedulerObjectInterface {
void start();
void stop();
}
每个作业都需要一个 ScheduledFuture 来停止,并且需要自动装配一个 TaskScheduler 来进行调度。这是一份工作的示例(您可以创建任意数量的工作):
@Component
public class MyFirstJob implements SchedulerObjectInterface {
private static final Logger log = LoggerFactory.getLogger(MyFirstJob.class);
public static final String JOB = "MyFirstJob";
@Autowired
JobRepository jobRepository;
private ScheduledFuture future;
@Autowired
private TaskScheduler scheduler;
@Override
public void start() {
future = scheduler.schedule(new Runnable() {
@Override
public void run() {
System.out.println(JOB + " Hello World! " + new Date());
}
}, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cron = cronConfig();
System.out.println(cron);
CronTrigger trigger = new CronTrigger(cron);
return trigger.nextExecutionTime(triggerContext);
}
});
}
@Override
public void stop() {
future.cancel(false);
}
// retrieve cron from database
private String cronConfig() {
JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB);
return byJobNameIgnoreCase.getCrontab();
}
}
最后我们可以将作业添加到协调器中:
@Configuration
public class SchedulerOrchestrator {
private static final Logger log = LoggerFactory.getLogger(SchedulerOrchestrator.class);
private static Map<String, SchedulerObjectInterface> schduledJobsMap = new HashMap<>();
@Autowired
JobRepository jobRepository;
@Autowired
MyFirstJob myFirstJob;
@Autowired
MySecondJob mySecondJob;
@Autowired
TaskScheduler scheduler;
@PostConstruct
public void initScheduler() {
schduledJobsMap.put(MyFirstJob.JOB, myFirstJob);
schduledJobsMap.put(MySecondJob.JOB, mySecondJob);
startAll();
}
public void restart(String job) {
stop(job);
start(job);
}
public void stop(String job) {
schduledJobsMap.get(job).stop();
}
public void start(String job) {
schduledJobsMap.get(job).start();
}
public void startAll() {
for (SchedulerObjectInterface schedulerObjectInterface : schduledJobsMap.values()) {
schedulerObjectInterface.start();
}
}
@Bean
public TaskScheduler scheduler() {
return new ThreadPoolTaskScheduler();
}
}
考虑这种方法。您可以根据您的观点和 运行 立即检查必要的任务,而不是添加和删除计划任务。这会更容易。检查 Quartz Scheduler,它的 CronExpression 有 isSatisfiedBy(Date date) 方法。
@Scheduled(cron = "5 * * * * *) // do not set seconds to zero, cause it may fit xx:yy:59
public void runTasks() {
LocalTime now = LocalTime.now(); // or Date now = new Date();
// check and run
}