一、序言
Java下Spring实现Quartz集群分布式(一)中的QuartzService 的源码
二、正文
QuartzService 的源代码:
package wade.system.service; import java.util.Date; import java.util.List; import java.util.Map; import org.quartz.*; /** * 定时任务管理 * */ public interface QuartzService { /** * 添加定时任务 * * @param name the name * @param group the group * @param clazz the clazz * @param cronExpression the cron expression * @param jobValue the job value * @param scheduler the scheduler * @param isJobListened the is job listened * @param isTriggerListened the is trigger listened * @return the date * @throws IllegalAccessException the illegal access exception * @throws InstantiationException the instantiation exception * @throws ClassNotFoundException the class not found exception * @throws SchedulerException the scheduler exception */ Date addJob(String name, String group, Class<? extends Job> clazz, String cronExpression, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListened, boolean isTriggerListened) throws IllegalAccessException, InstantiationException, ClassNotFoundException, SchedulerException; /** * Add job by simple trigger date. * * @param name the name * @param group the group * @param clazz the clazz * @param simpleTrigger the simple trigger * @param jobValue the job value * @param scheduler the scheduler * @param isJobListened the is job listened * @param isTriggerListened the is trigger listened * @return the date * @throws SchedulerException the scheduler exception * @throws IllegalAccessException the illegal access exception * @throws InstantiationException the instantiation exception * @throws ClassNotFoundException the class not found exception */ Date addJobBySimpleTrigger(String name, String group, Class<? extends Job> clazz, Trigger simpleTrigger, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListened, boolean isTriggerListened) throws SchedulerException, IllegalAccessException, InstantiationException, ClassNotFoundException; /** * 立即执行一次 * * @param name the name * @param group the group * @param clazz the clazz * @param jobValue the job value * @param scheduler the scheduler * @param isJobListened the is job listened * @param isTriggerListened the is trigger listened * @throws SchedulerException the scheduler exception * @throws IllegalAccessException the illegal access exception * @throws InstantiationException the instantiation exception * @throws ClassNotFoundException the class not found exception */ void immediatelyExecuteJobOneTime(String name, String group, Class<? extends Job> clazz, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListened, boolean isTriggerListened) throws SchedulerException, IllegalAccessException, InstantiationException, ClassNotFoundException; /** * 删除定时任务 * * @param name the name * @param group the group * @param scheduler the scheduler * @throws SchedulerException the scheduler exception */ void removeJob(String name, String group, Scheduler scheduler) throws SchedulerException; /** * 暂停定时任务 * * @param name the name * @param group the group * @param scheduler the scheduler * @throws SchedulerException the scheduler exception */ void pauseJob(String name, String group, Scheduler scheduler) throws SchedulerException; /** * 重新开始定时任务 * * @param name the name * @param group the group * @param scheduler the scheduler * @throws SchedulerException the scheduler exception */ void resumeJob(String name, String group, Scheduler scheduler) throws SchedulerException; /** * 修改定时任务时间 * * @param name the name * @param group the group * @param cronExpression the cron expression * @param scheduler the scheduler * @return the date * @throws SchedulerException the scheduler exception */ Date modifyTime(String name, String group, String cronExpression, Scheduler scheduler) throws SchedulerException; /** * 修改定时任务的时间和参数 * * @param name the name * @param group the group * @param clazz the clazz * @param cronExpression the cron expression * @param jobValue the job value * @param scheduler the scheduler * @param isJobListener the is job listener * @return the date * @throws SchedulerException the scheduler exception * @throws IllegalAccessException the illegal access exception * @throws InstantiationException the instantiation exception * @throws ClassNotFoundException the class not found exception */ Date modifyJobValueAndTime(String name, String group, Class<? extends Job> clazz, String cronExpression, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListener) throws SchedulerException, IllegalAccessException, InstantiationException, ClassNotFoundException; /** * 任务开始 * * @param scheduler the scheduler * @throws SchedulerException the scheduler exception */ void start(Scheduler scheduler) throws SchedulerException; /** * 任务关闭 * * @param scheduler the scheduler * @throws SchedulerException the scheduler exception */ void shutdown(Scheduler scheduler) throws SchedulerException; /** * 获取下次执行时间 * * @param name the name * @param group the group * @param scheduler the scheduler * @return the next fire time * @throws SchedulerException the scheduler exception */ Date getNextExecutionTime(String name, String group, Scheduler scheduler) throws SchedulerException; /** * 检查作业是否正在执行 * * @param key the key * @param scheduler the scheduler * @return the boolean * @throws SchedulerException the scheduler exception */ boolean checkJobStatus(String key, Scheduler scheduler) throws SchedulerException; /** * 初始化所有的jobListener * * @return boolean */ boolean initALLJobListener(List<JobKey> jobKeyList); /** * 根据组来初始化JobListener * * @param groups key为GROUP名字,value为监听器路径 * @return */ boolean initGroupJobListener(Map<String, String> groups); }
QuartzServiceImpl的源代码:
package wade.system.service.impl; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; import java.util.*; import org.apache.commons.lang3.StringUtils; import org.quartz.*; import org.quartz.impl.matchers.GroupMatcher; import org.quartz.impl.matchers.KeyMatcher; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; import wade.system.service.QuartzService; @Repository("quartzService") public class QuartzServiceImpl implements QuartzService { /** * 日志记录 */ private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(QuartzServiceImpl.class); /** * 调度程序工厂类 */ @Autowired SchedulerFactoryBean schedulerFactoryBean; @Override public Date addJob(String name, String group, Class<? extends Job> clazz, String cronExpression, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListened, boolean isTriggerListened) throws IllegalAccessException, InstantiationException, ClassNotFoundException, SchedulerException { Date nextFireTime = null; //构造任务 JobDetail job = newJob(clazz).withIdentity(name, group).storeDurably(true).build(); //构造任务触发器 Trigger trg = newTrigger().withIdentity(name, group).withSchedule(cronSchedule(cronExpression) .withMisfireHandlingInstructionDoNothing ()).build(); if (jobValue != null) { for (String key : jobValue.keySet()) { job.getJobDataMap().put(key, jobValue.get(key)); } } isJobListened = false; if (isJobListened) { scheduler = addJobListener(job.getKey(), clazz, scheduler); } if (isTriggerListened) { scheduler = addTriggerListened(trg, clazz, scheduler); } //将作业添加到调度器 nextFireTime = scheduler.scheduleJob(job, trg); LOGGER.info("新增作业=> [作业名称:" + name + " 作业组:" + group + "] "); return nextFireTime; } @Override public void immediatelyExecuteJobOneTime(String name, String group, Class<? extends Job> clazz, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListened, boolean isTriggerListened) throws SchedulerException, IllegalAccessException, InstantiationException, ClassNotFoundException { JobKey jobKey = new JobKey(name, group); JobDataMap jobDataMap = new JobDataMap(); if (jobValue != null) { for (String key : jobValue.keySet()) { jobDataMap.put(key, jobValue.get(key)); } } isJobListened = false; if (isJobListened) { scheduler = addJobListener(jobKey, clazz, scheduler); } scheduler.triggerJob(jobKey, jobDataMap); } @Override public boolean checkJobStatus(String key, Scheduler scheduler) throws SchedulerException { List<JobExecutionContext> jobExecutionContexts = scheduler.getCurrentlyExecutingJobs(); for (JobExecutionContext job : jobExecutionContexts) { JobDetail jobDetail = job.getJobDetail(); JobKey jobKey = jobDetail.getKey(); if (jobKey.getName().equals(key)) { return true; } } return false; } /** * 添加作业监听程序 * * @param jobKey * @param clazz * @param scheduler */ private Scheduler addJobListener(JobKey jobKey, Class<? extends Job> clazz, Scheduler scheduler) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SchedulerException { String tempPath = clazz.getName() + "Listener"; String listenerFilePath = buildEntirePath(tempPath); Object jobListener = Class.forName(listenerFilePath).newInstance(); KeyMatcher<JobKey> keyMatcher = KeyMatcher.keyEquals(jobKey); scheduler.getListenerManager().addJobListener((JobListener) jobListener, keyMatcher); return scheduler; } private Scheduler addTriggerListened(Trigger trigger, Class<? extends Job> clazz, Scheduler scheduler) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SchedulerException { String tempPath = clazz.getName() + "TListener"; String listenerFilePath = buildEntirePath(tempPath); TriggerListener triggerListener = (TriggerListener) Class.forName(listenerFilePath).newInstance(); KeyMatcher<TriggerKey> keyMatcher = KeyMatcher.keyEquals(trigger.getKey()); scheduler.getListenerManager().addTriggerListener(triggerListener, keyMatcher); return scheduler; } /** * 构建完整的Listener文件路径 * * @param tempPath * @return */ private String buildEntirePath(String tempPath) { String[] packageNames = tempPath.split("\\."); List<String> list = new ArrayList<>(); Arrays.asList(packageNames).forEach(s -> { list.add(s); }); list.add(list.size() - 1, "listener"); return StringUtils.join(list, "."); } @Override public Date addJobBySimpleTrigger(String name, String group, Class<? extends Job> clazz, Trigger simpleTrigger, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListened, boolean isTriggerListened) throws SchedulerException, IllegalAccessException, InstantiationException, ClassNotFoundException { Date nextFireTime = null; //构造任务 JobDetail job = newJob(clazz).withIdentity(name, group).build(); if (jobValue != null) { for (String key : jobValue.keySet()) { job.getJobDataMap().put(key, jobValue.get(key)); } } //将作业添加到调度器 Trigger trigger = simpleTrigger; isJobListened = false; if (isJobListened) { scheduler = addJobListener(job.getKey(), clazz, scheduler); } if (isTriggerListened) { scheduler = addTriggerListened(trigger, clazz, scheduler); } nextFireTime = scheduler.scheduleJob(job, trigger); LOGGER.info("新增作业=> [作业名称:" + name + " 作业组:" + group + "] "); return nextFireTime; } @Override public void removeJob(String name, String group, Scheduler scheduler) throws SchedulerException { TriggerKey tk = TriggerKey.triggerKey(name, group); scheduler.pauseTrigger(tk);//停止触发器 scheduler.unscheduleJob(tk);//移除触发器 JobKey jobKey = JobKey.jobKey(name, group); scheduler.deleteJob(jobKey);//删除作业 LOGGER.info("删除作业=> [作业名称:" + name + " 作业组:" + group + "] "); } @Override public void pauseJob(String name, String group, Scheduler scheduler) throws SchedulerException { JobKey jobKey = JobKey.jobKey(name, group); scheduler.pauseJob(jobKey); LOGGER.info("暂停作业=> [作业名称:" + name + " 作业组:" + group + "] "); } @Override public void resumeJob(String name, String group, Scheduler scheduler) throws SchedulerException { JobKey jobKey = JobKey.jobKey(name, group); scheduler.resumeJob(jobKey); LOGGER.info("恢复作业=> [作业名称:" + name + " 作业组:" + group + "] "); } @Override public Date modifyTime(String name, String group, String cronExpression, Scheduler scheduler) throws SchedulerException { TriggerKey tk = TriggerKey.triggerKey(name, group); //构造任务触发器 Trigger trg = newTrigger().withIdentity(name, group) .forJob(name, group).withSchedule(cronSchedule(cronExpression) .withMisfireHandlingInstructionDoNothing()).build(); Date nextFireTime = scheduler.rescheduleJob(tk, trg); LOGGER.info("修改作业触发时间=> [作业名称:" + name + " 作业组:" + group + "] "); return nextFireTime; } @Override public Date modifyJobValueAndTime(String name, String group, Class<? extends Job> clazz, String cronExpression, Map<String, String> jobValue, Scheduler scheduler, boolean isJobListener) throws SchedulerException, IllegalAccessException, InstantiationException, ClassNotFoundException { TriggerKey oldTk = TriggerKey.triggerKey(name, group); scheduler.pauseTrigger(oldTk);//停止触发器 scheduler.unscheduleJob(oldTk);//移除触发器 JobKey jobKey = JobKey.jobKey(name, group); scheduler.deleteJob(jobKey);//删除作业 Date nextFireTime = null; //构造任务 JobDetail job = newJob(clazz).withIdentity(name, group).storeDurably(true).build(); for (String key : jobValue.keySet()) { job.getJobDataMap().put(key, jobValue.get(key)); } if (isJobListener) { scheduler = addJobListener(job.getKey(), clazz, scheduler); } //构造任务触发器 Trigger trg = newTrigger().withIdentity(name, group) .forJob(job).withSchedule(cronSchedule(cronExpression) .withMisfireHandlingInstructionDoNothing()).build(); nextFireTime = scheduler.scheduleJob(job, trg); LOGGER.info("修改作业触发时间和参数=> [触发器名称:" + name + " 作业组:" + group + "] "); return nextFireTime; } @Override public void start(Scheduler scheduler) throws SchedulerException { scheduler.start(); LOGGER.info("启动调度器 "); } @Override public void shutdown(Scheduler scheduler) throws SchedulerException { scheduler.shutdown(); LOGGER.info("停止调度器 "); } @Override public Date getNextExecutionTime(String name, String group, Scheduler scheduler) throws SchedulerException { TriggerKey triggerKey = TriggerKey.triggerKey(String.valueOf(name), group); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); return trigger.getNextFireTime(); } @Override public boolean initALLJobListener(List<JobKey> jobKeyList) { Scheduler scheduler = schedulerFactoryBean.getScheduler(); boolean result = false; try { for (JobKey jobKey : jobKeyList) { JobDetail jd = scheduler.getJobDetail(jobKey); if (jd != null) { LOGGER.info("my ID is " + jd.getKey() + "my Class is " + jd.getJobClass().toString()); addJobListener(jobKey, jd.getJobClass(), scheduler); } } result = true; } catch (Exception e) { LOGGER.error("批量绑定监听器异常", e); } return result; } @Override public boolean initGroupJobListener(Map<String, String> groups) { Scheduler scheduler = schedulerFactoryBean.getScheduler(); boolean result = false; try { for (Map.Entry<String, String> entry : groups.entrySet()) { GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(entry.getKey()); Object clazz = Class.forName(entry.getValue()).newInstance(); scheduler.getListenerManager().addJobListener((JobListener) clazz, groupMatcher); scheduler.getListenerManager().getJobListeners().forEach(jobListener -> { LOGGER.info(jobListener.getName()); }); } result = true; } catch (Exception e) { LOGGER.error("批量绑定监听器异常", e); } return result; } }