做项目的时候需要实现定时任务的动态配置,在网上一番搜集后实现了一种reschedual的方式,结果测试发现,在项目启动之后,初始cron被修改后,原cron必须执行过一次以后新cron才能生效。之后用了下面的方法,解决了这个问题。
public class JobScheduleService {
@Resource
public Scheduler scheduler;
@Autowired
JobEntityMapper jobEntityMapper;
public JobDetail getJobDetail(Class clazz,String jobname,JobDataMap data) {
JobDetail job = JobBuilder.newJob(clazz).withIdentity(jobname, Scheduler.DEFAULT_GROUP).setJobData(data).build();
return job;
}
public CronTrigger getCronTrigger(String triggerName,String triggerGroup,String cront,JobKey jk,Date startTime) {
CronTrigger ct = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(cront)).forJob(jk).startAt(startTime)
.build();
return ct;
}
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* 项目启动时,从数据库中取出job,启动默认定时任务
*/
@PostConstruct
private void initScheduleJobs() throws Exception {
List<JobEntity> jobs = jobEntityMapper.selectAll();
for (JobEntity job : jobs) {
startUpAJob(job.getJobname(), job.getJobclass(), job.getCron());
}
}
//a添加或更新一个新的任务,并启动,启动成功后将任务配置存储进数据库
public void addOrUpdateCrontTask(String jobName,String jobClass,String cron) throws Exception {
if (jobName == null||jobClass == null ||cron == null) {
throw new Exception("jobName,jobClass,cron can not be null");
}
startUpAJob(jobName,jobClass,cron);
//a任务成功启动后更新到数据库中
storeJobEntity(jobName,jobClass,cron);
}
//a将任务配置存储进数据库
private void storeJobEntity(String jobName,String jobClass,String cron) {
int jobCount = jobEntityMapper.countByJobName(jobName);
JobEntity job = new JobEntity();
job.setJobname(jobName);
job.setJobclass(jobClass);
job.setCron(cron);
System.out.println(job);
if(jobCount == 0) {
jobEntityMapper.insertSelective(job);
}else {
jobEntityMapper.updateByJobName(job);
}
}
//a启动一个任务,如果这个任务存在,更新,不存在,添加
private void startUpAJob(String jobName,String jobClass,String cron) throws Exception {
Date startdate = new Date();
Class clazz = Class.forName(jobClass);
Scheduler scheduler = null;
try {
scheduler = this.scheduler;
JobDataMap data = new JobDataMap();
//data.put("extraParams",job.getExtraParams());
JobDetail jobDetail = this.getJobDetail(clazz,jobName,data);
CronTrigger cronTrigger = null;
String triggerName = jobName;
JobKey jk = JobKey.jobKey(jobName, scheduler.DEFAULT_GROUP);
TriggerKey tk = TriggerKey.triggerKey(triggerName,scheduler.DEFAULT_GROUP);
JobDetail existJobDetail = scheduler.getJobDetail(jk);
if (existJobDetail != null) {
Trigger trigger = scheduler.getTrigger(tk);//getTrigger(triggerName,scheduler.DEFAULT_GROUP);
if (trigger instanceof CronTrigger) {
//CronTrigger ct = (CronTrigger) trigger;
//ct.getTriggerBuilder().withIdentity(triggerName, scheduler.DEFAULT_GROUP).withSchedule(CronScheduleBuilder.cronSchedule(cron)).forJob(jk).startAt(startdate).build();
//scheduler.rescheduleJob(tk, ct);
this.removeJob(jobName);
cronTrigger = this.getCronTrigger(triggerName, scheduler.DEFAULT_GROUP, cron,jk,startdate);
scheduler.scheduleJob(jobDetail, cronTrigger);
} else {
throw new Exception("trigger Class Type exception : "
+ trigger.getClass().getName());
}
} else {
cronTrigger = this.getCronTrigger(triggerName, scheduler.DEFAULT_GROUP, cron,jk,startdate);
scheduler.scheduleJob(jobDetail, cronTrigger);
}
if(scheduler.isShutdown()){
scheduler.start();
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
//a删除一个任务
public void removeJob(String jobName) throws SchedulerException {
// this.scheduler.deleteJob(jobName, scheduler.DEFAULT_GROUP);
this.scheduler.deleteJob(JobKey.jobKey(jobName, Scheduler.DEFAULT_GROUP));
}
public void updateJobCron(String jobName,String newCron) throws Exception {
if(jobName.equals("warningLostService")) {
this.addOrUpdateCrontTask(jobName, "com.ibm.cdl.itaas.billing.backend.jobs.CheckServiceCrashJob", newCron);
log.info("更改job:"+jobName+" 新的cron: "+newCron);
}else if(jobName.equals("warningBueChange")) {
this.addOrUpdateCrontTask(jobName, "com.ibm.cdl.itaas.billing.backend.jobs.BueCheckJob", newCron);
log.info("更改job:"+jobName+" 新的cron: "+newCron);
}
}
}
获取到那个job,从schedual中删除他,再用新的cron生成这个job,就可以达到动态配置的效果,且能立即生效