我使用Quartz CronScheduler每15分钟执行一次作业。每次执行作业时,都会检查DB以查找cron表达式中的任何更改,并更新作业调度程序以进行下一次运行。我已通过以下方式实现了上述内容:
@Service
public class QuartzSchedulerService {
private static final Logger LOG = LoggerFactory.getLogger(QuartzSchedulerService.class);
private Scheduler scheduler;
@PostConstruct
private void init() {
try {
scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
} catch (Exception e) {
LOG.error("Unable to start quartz scheduler", e);
}
}
@PreDestroy
private void destroy() {
try {
scheduler.shutdown();
} catch (Exception e) {
LOG.error("Unable to shutdown quartz scheduler", e);
}
}
public void registerCronJob(Class<? extends Job> jobClass, String cronExpression) {
try {
String jobName = jobClass.getSimpleName();
CronScheduleBuilder cronBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName).build();
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName).withSchedule(cronBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
LOG.info("Registered Cron Job:" + jobName + " " + jobDetail.getKey());
} catch (Exception e) {
LOG.error("Unable to register cron job", e);
}
}
public void updateCronSchedule(Class<? extends Job> jobClass, String cronExpression) {
try {
String jobName = jobClass.getSimpleName();
CronScheduleBuilder cronBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
CronTrigger newCronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName).withSchedule(cronBuilder).build();
scheduler.rescheduleJob(TriggerKey.triggerKey(jobName), newCronTrigger);
LOG.info("Updated Cron Job:" + jobName + " " + newCronTrigger.getJobKey());
LOG.info("Jobs executed: " + scheduler.getMetaData().getNumberOfJobsExecuted());
} catch (Exception e) {
LOG.error("Unable to reschedule cron job", e);
}
}
}
实现Job接口的类如下:
@Component
@DisallowConcurrentExecution
public class PropertiesReloadJob implements Job {
private static final Logger LOG = LoggerFactory.getLogger(PropertiesReloadJob.class);
@Autowired
private QuartzSchedulerService schedulerService;
@Autowired
private PropertiesService propertiesService;
public void loadAtStartup() {
load();
LOG.info("--- Registerting PropertiesReload Cron Job ---");
schedulerService.registerCronJob(PropertiesReloadJob.class, propertiesService.getCacheReloadCronExpression());
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
load();
LOG.info("--- Updating Pro Cron Job ---");
schedulerService.updateCronSchedule(PropertiesReloadJob.class, propertiesService.getCacheReloadCronExpression());
}
public void load(){
// Load properties from DB
}
在上下文初始化期间调用loadAtStartup()方法,然后在每15分钟调用一次execute()方法。
使用的cron表达式为:0 0/15 * 1/1 * ? *
现在,问题如下: 假设作业从3:00:00开始,它将执行多次,直到3:00:01,而不是仅执行一次。
接下来,作业将在3:15:00开始,并且可以再次运行至3:15:01。
每次作业执行的次数都不同。
我不确定导致此行为的原因。我用cronmaker测试了cron表达式。
有人可以在这里指出错误吗?