Quartz動態添加、修改和刪除定時任務java
在項目中有一個需求,須要靈活配置調度任務時間,剛開始用的Java自帶的java.util.Timer類,經過調度一個java.util.TimerTask任務,雖然可以執行,可是在內部類裏不能調用service,仍是有不少不變,後來在網上查了不少資料,雖然本人級別不夠,可是經過各類組合嘗試,終於找到了方法,而後才發現竟是如此簡單,汗顏。。。下面來分享給你們。spring
1.說明: apache
spring3.1如下的版本必須使用quartz1.x系列,3.1以上的版本才支持quartz 2.x。在quartz1.x系列中org.quartz.CronTrigger是個類,而在quartz2.x系列中org.quartz.CronTrigger變成了接口,從而形成沒法用spring的方式配置quartz的觸發器(trigger)。json
我使用的quartz版本是2.2.1 。xcode
最終實現的功能:ide
1) 可添加新任務,刪除任務,更新任務,暫停任務,恢復任務 ;函數
2) 動態添加定時任務,按時執行相應的邏輯 ;ui
2.配置即便用spa
1)首先咱們要一個定時器管理類,這個很重要。全部的定時器操做都要用到這個類。.net
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;
import org.quartz.JobBuilder.newJob; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.quartz.impl.StdSchedulerFactory; /** * * @Description * @author qgw * 2016 上午10:05:59 ^_^ */ public class QuartzManager { private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory(); private static String JOB_GROUP_NAME = "MY_JOBGROUP_NAME"; private static String TRIGGER_GROUP_NAME = "MY_TRIGGERGROUP_NAME"; /** * @Description: 添加一個定時任務,使用默認的任務組名,觸發器名,觸發器組名 * @param jobName 任務名 * @param cls 任務 * @param time 時間設置,參考quartz說明文檔 * qgw 2016年1月21日 下午3:30:10 ^_^ */ @SuppressWarnings("unchecked") public static void addJob(String jobName, Class cls, String time,Object scheduleJob) { try { Scheduler sched = gSchedulerFactory.getScheduler(); JobDetail job = newJob(cls) .withIdentity(jobName, JOB_GROUP_NAME) .build(); // 添加具體任務方法 job.getJobDataMap().put("scheduleJob", scheduleJob); // 表達式調度構建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time); // 按新的cronExpression表達式構建一個新的trigger Trigger trigger = TriggerBuilder .newTrigger() .withIdentity(jobName, TRIGGER_GROUP_NAME) .withSchedule(scheduleBuilder).build(); //交給scheduler去調度 sched.scheduleJob(job, trigger); // 啓動 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 添加一個定時任務 * @param jobName 任務名 * @param jobGroupName 任務組名 * @param triggerName 觸發器名 * @param triggerGroupName 觸發器組名 * @param jobClass 任務 * @param time 時間設置,參考quartz說明文檔 * qgw 2016年1月21日 下午3:27:00 ^_^ */ @SuppressWarnings("unchecked") public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String time) { try { Scheduler sched = gSchedulerFactory.getScheduler(); JobDetail job = newJob(jobClass) .withIdentity(jobName, jobGroupName) .build(); // 表達式調度構建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time); // 按新的cronExpression表達式構建一個新的trigger Trigger trigger = TriggerBuilder .newTrigger() .withIdentity(triggerName, triggerGroupName) .withSchedule(scheduleBuilder).build(); sched.scheduleJob(job, trigger); // 啓動 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 修改一個任務的觸發時間(使用默認的任務組名,觸發器名,觸發器組名) * @param jobName * @param time * qgw 2016年1月21日 下午3:28:34 ^_^ */ @SuppressWarnings("unchecked") public static void modifyJobTime(String jobName, String time) { TriggerKey triggerKey = TriggerKey.triggerKey( jobName, TRIGGER_GROUP_NAME); try { Scheduler sched = gSchedulerFactory.getScheduler(); CronTrigger trigger =(CronTrigger) sched.getTrigger(triggerKey); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { CronScheduleBuilder scheduleBuilder =CronScheduleBuilder.cronSchedule(time); //按新的cronExpression表達式從新構建trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey) .withSchedule(scheduleBuilder).build(); //按新的trigger從新設置job執行 sched.rescheduleJob(triggerKey, trigger); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 修改一個任務的觸發時間 * @param triggerName * @param triggerGroupName * @param time * @author qgw * @date 2016年1月27日 下午4:45:15 ^_^ */ public static void modifyJobTime(String triggerName, String triggerGroupName, String time) { TriggerKey triggerKey = TriggerKey.triggerKey( triggerName, triggerGroupName); try { Scheduler sched = gSchedulerFactory.getScheduler(); CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { // trigger已存在,則更新相應的定時設置 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule(time); // 按新的cronExpression表達式從新構建trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey) .withSchedule(scheduleBuilder).build(); // 按新的trigger從新設置job執行 sched.resumeTrigger(triggerKey); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description 移除一個任務(使用默認的任務組名,觸發器名,觸發器組名) * @param jobName * @author qgw * @date 2016年1月29日 下午2:21:16 ^_^ */ public static void removeJob(String jobName) { TriggerKey triggerKey = TriggerKey.triggerKey( jobName, TRIGGER_GROUP_NAME); JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_NAME); try { Scheduler sched = gSchedulerFactory.getScheduler(); Trigger trigger = (Trigger) sched.getTrigger(triggerKey); if (trigger == null) { return; } sched.pauseTrigger(triggerKey);;// 中止觸發器 sched.unscheduleJob(triggerKey);// 移除觸發器 sched.deleteJob(jobKey);// 刪除任務 } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 移除一個任務 * @param jobName * @param jobGroupName * @param triggerName * @param triggerGroupName * @author qgw * @date 2016年1月29日 下午2:21:16 ^_^ */ public static void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) { TriggerKey triggerKey = TriggerKey.triggerKey( jobName, triggerGroupName); JobKey jobKey = JobKey.jobKey(jobName, jobGroupName); try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.pauseTrigger(triggerKey);// 中止觸發器 sched.unscheduleJob(triggerKey);// 移除觸發器 sched.deleteJob(jobKey);// 刪除任務 } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description:暫停一個任務 * @param jobName * @param jobGroupName * qgw 2016年1月22日 下午4:24:55 ^_^ */ public static void pauseJob(String jobName, String jobGroupName) { JobKey jobKey =JobKey.jobKey(jobName, jobName); try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.pauseJob(jobKey); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @Description:暫停一個任務(使用默認組名) * @param jobName * @param jobGroupName * qgw 2016年1月22日 下午4:24:55 ^_^ */ public static void pauseJob(String jobName) { JobKey jobKey =JobKey.jobKey(jobName, JOB_GROUP_NAME); try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.pauseJob(jobKey); } catch (SchedulerException e) { e.printStackTrace(); } } /** * @Description:啓動全部定時任務 * @author qgw * @date 2016年1月29日 下午2:21:16 ^_^ */ public static void startJobs() { try { Scheduler sched = gSchedulerFactory.getScheduler(); sched.start(); } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description 關閉全部定時任務 * @author qgw * @date 2016年1月25日 下午2:26:54 ^_^ */ public static void shutdownJobs() { try { Scheduler sched = gSchedulerFactory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { throw new RuntimeException(e); } } }
這樣咱們就能夠經過這個類對定時任務作 添加新任務,刪除任務,更新任務,暫停任務,恢復任務。另外說明一點,執行定時任務的類爲傳入的參數Class cls。這個類爲反射出來的類,不歸spring管理,因此在這個類裏注入是不成功的,須要經過spring的上下文獲取bean,並set到構造函數中去進行初始化。
調用類舉例:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.json.JSONObject; import org.apache.log4j.Logger; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.context.ApplicationContext; /** * 定時任務運行(反射出來的類) * @Description * @author qgw * 2016 下午2:39:37 ^_^ */ @DisallowConcurrentExecution public class QuartzJobFactory implements Job { private static final Logger log = Logger.getLogger(""); @Override public void execute(JobExecutionContext context) throws JobExecutionException { log.info("任務運行開始-------- start --------"); try { //ScheduleJob任務運行時具體參數,可自定義 ScheduleJob scheduleJob =(ScheduleJob) context.getMergedJobDataMap().get( "scheduleJob"); }catch (Exception e) { log.info("捕獲異常==="+e); } log.info("任務運行結束-------- end --------"); } }
2)下面就是調用了
import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.json.JSONObject; import org.apache.log4j.Logger; /** * 加載定時任務 * @Description * @author qgw * 2016 下午2:24:58 ^_^ */ @SuppressWarnings("unchecked") public class LoadTask { private static final Logger log = Logger.getLogger(""); /** * @param sendTime 發送時間 * @return * @author qgw * @date 2016年1月26日 下午3:39:13 ^_^ */ public static boolean timerTask(long sendTime,long msgId) { String cron = QuartzManager.getQuartzTime(Util.toString(sendTime));//得到quartz時間表達式,此方法本身寫 ScheduleJob job = new ScheduleJob(); String jobName = msgId+"_job"; job.setJobId(msgId); job.setJobName(jobName); job.setCreTime(nowTime); job.setJobCron(cron); job.setJobTime(sendTime); job.setJobGroup("MY_JOBGROUP_NAME"); job.setJobDesc(desc); try { //刪除已有的定時任務 QuartzManager.removeJob(jobName); //添加定時任務 QuartzManager.addJob(jobName, QuartzJobFactory.class, cron,job); return true; } catch (Exception e) { log.info("加載定時器錯誤:"+e); return false; } } }
3.注意
因爲定時任務不斷添加,並且不被銷燬,時間長了的話可能會有內存溢出的可能,因此最好仍是添加定時任務,把天天過時的定時任務清理一下,我的建議。
4.總結
關於quartz定時器動態添加定時任務的各類方法,要基於項目需求去不斷改進。目前此方法已投入使用,可能還有不完善的地方,但願各位大神來補充。
5.參考
參考文章:http://www.dexcoder.com/selfly/article/311
文章轉載至 http://blog.csdn.net/u012414587/article/details/50605861