quartz定時器的使用,定時任務的動態增刪改
阿新 • • 發佈:2018-12-16
目錄
一、簡介:
Java的定時任務通常使用以下方式:
- 使用JDK自帶的Timer
- 使用quartz框架
這裡主要是使用quartz來實現。Quartz是一款效能強大的定時任務排程器。開發人員可以使用Quartz讓任務在特定時間特定階段進行執行。Quartz提供兩種型別的任務觸發方式,一種是按指定時間間隔觸發任務,另一種是按指定日曆時間觸發任務。
二、使用:
1.新增maven依賴包:
<!-- Quartz --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.3.0</version> </dependency>
2.編寫任務bean,主要封裝了定時任務相關的資訊
package cn.zzs.entity; /** * 封裝Job資訊 */ public class ScheduleJob { /** job名稱 **/ private String jobName; /** job組 **/ private String jobGroupName = "QUARTZ_JOB_GROUP";// 預設組名 /** trigger名稱 **/ private String triggerName;// 未賦值時預設返回jobName /** jtrigger組 **/ private String triggerGroupName = "QUARTZ_TRIGGER_GROUP";// 預設組名 /** cron時間表達式 **/ private String cronExpression; /** 任務執行的類名:service類名 **/ private String springId; /** 任務執行的類名:包名+類名 **/ private String beanClass; /** 任務執行的方法名 **/ private String methodName; /** 是否自定義 **/ private String isZdy = "n";// 反射時預設不指定引數型別 public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroupName() { return jobGroupName; } public void setJobGroupName(String jobGroupName) { this.jobGroupName = jobGroupName; } public String getTriggerName() { if(triggerName == null || "".equals(triggerName)) { return jobName; }else { return triggerName; } } public void setTriggerName(String triggerName) { this.triggerName = triggerName; } public String getTriggerGroupName() { return triggerGroupName; } public void setTriggerGroupName(String triggerGroupName) { this.triggerGroupName = triggerGroupName; } public String getCronExpression() { return cronExpression; } public void setCronExpression(String cronExpression) { this.cronExpression = cronExpression; } public String getSpringId() { return springId; } public void setSpringId(String springId) { this.springId = springId; } public String getBeanClass() { return beanClass; } public void setBeanClass(String beanClass) { this.beanClass = beanClass; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public String getIsZdy() { return isZdy; } public void setIsZdy(String isZdy) { this.isZdy = isZdy; } }
3.編寫quartz工具類,實現了一個任務的新增,修改執行時間,暫停,恢復等等
package cn.zzs.utils; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.quartz.impl.StdSchedulerFactory; import cn.zzs.entity.ScheduleJob; /** * quzrtz工具類 */ public class QuartzManager { private static SchedulerFactory schedulerFactory = new StdSchedulerFactory(); /** * 新增一個定時任務 */ public static void addJob(ScheduleJob scheduleJob) { try { Scheduler scheduler = schedulerFactory.getScheduler(); // 任務名,任務組,任務執行類 JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class) .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroupName()) .build(); jobDetail.getJobDataMap().put("scheduleJob", scheduleJob); //JobDataMap可用於儲存任何您希望在執行時對作業例項可用的資料物件 // 觸發器 CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getTriggerName(), scheduleJob.getTriggerGroupName()) .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())) .build(); // 排程容器設定JobDetail和Trigger scheduler.scheduleJob(jobDetail, trigger); // 啟動 if (!scheduler.isShutdown()) { scheduler.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * 修改一個任務的觸發時間 */ public static void modifyJobTime(ScheduleJob scheduleJob) { try { Scheduler scheduler = schedulerFactory.getScheduler(); TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getTriggerName(), scheduleJob.getTriggerGroupName()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(scheduleJob.getCronExpression())) { trigger = //TriggerBuilder.newTrigger() trigger.getTriggerBuilder() .withIdentity(triggerKey) .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())) .build(); // 修改一個任務的觸發時間 scheduler.rescheduleJob(triggerKey, trigger); } } catch (Exception e) { throw new RuntimeException(e); } } /** * 暫停一個任務 */ public static void pauseJob(ScheduleJob scheduleJob) { try { Scheduler scheduler = schedulerFactory.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroupName()); scheduler.pauseJob(jobKey); } catch (Exception e) { e.printStackTrace(); } } /** * 恢復一個任務 */ public static void resumeJob(ScheduleJob scheduleJob) { try { Scheduler scheduler = schedulerFactory.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroupName()); scheduler.resumeJob(jobKey); } catch (Exception e) { e.printStackTrace(); } } /** * 立即執行一個任務 * * 說明: * 這裡的立即執行,只會執行一次,方便測試時用。 * quartz是通過臨時生成一個trigger的方式來實現的,這個trigger將在本次任務執行完成之後自動刪除。 */ public static void triggerJob(ScheduleJob scheduleJob) { try { Scheduler scheduler = schedulerFactory.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroupName()); scheduler.triggerJob(jobKey); } catch (Exception e) { e.printStackTrace(); } } /** * 移除一個任務 */ public static void removeJob(ScheduleJob scheduleJob) { try { Scheduler scheduler = schedulerFactory.getScheduler(); TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getTriggerName(), scheduleJob.getTriggerGroupName()); // 停止觸發器 scheduler.pauseTrigger(triggerKey); // 移除觸發器 scheduler.unscheduleJob(triggerKey); // 刪除任務 scheduler.deleteJob(JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroupName())); } catch (Exception e) { throw new RuntimeException(e); } } /** * * 啟動所有定時任務 */ public static void startJobs() { try { Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.start(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 關閉所有定時任務 */ public static void shutdownJobs() { try { Scheduler scheduler = schedulerFactory.getScheduler(); if (!scheduler.isShutdown()) { scheduler.shutdown(); } } catch (Exception e) { throw new RuntimeException(e); } } }
4.編寫自定義的Job,這裡面寫要定時執行的任務(我這裡利用反射去執行ScheduleJob中封裝的方法)
package cn.zzs.utils;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import cn.zzs.entity.ScheduleJob;
/**
* Job實現類:
* 計劃任務執行處(反射執行)
*/
public class QuartzJobFactory implements Job {
public final Logger log = Logger.getLogger(this.getClass());
/**
* 這個方法裡寫需要定時執行的任務
* 我這裡已經將需要執行的類名和方法名封裝進ScheduleJob中,因此此方法利用反射獲取ScheduleJob中的資訊去執行
*/
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 獲取建立Job時傳遞的資料
ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
// 利用反射去執行
ScheduleJobUtils.invokMethod(scheduleJob);
}
}
5.擴充套件工具類
package cn.zzs.utils;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import cn.zzs.entity.ScheduleJob;
/**
* Job執行工具類,利用反射執行相應的類的對應方法
*/
public class ScheduleJobUtils {
public final static Logger log = Logger.getLogger(ScheduleJobUtils.class);
/**
* 通過反射呼叫scheduleJob中定義的方法
*/
public static void invokMethod(ScheduleJob scheduleJob) {
Object object = null;
Class<?> clazz = null;
if (StringUtils.isNotBlank(scheduleJob.getSpringId())) {
object = SpringUtils.getBean(scheduleJob.getSpringId());
clazz = object.getClass();
} else if (StringUtils.isNotBlank(scheduleJob.getBeanClass())) {
try {
clazz = Class.forName(scheduleJob.getBeanClass());
object = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
if (object == null) {
log.error(getNow() + " >任務名稱 = [" + scheduleJob.getJobName() + "]--------未啟動成功,請檢查是否配置正確!!!");
return;
}
try {
// 如果是自定義任務
if ("y".equals(scheduleJob.getIsZdy())) {
Method method = clazz.getDeclaredMethod(scheduleJob.getMethodName(), new Class[] { ScheduleJob.class });
method.invoke(object, scheduleJob);
} else {
Method method = clazz.getDeclaredMethod(scheduleJob.getMethodName(), new Class[] {});
method.invoke(object, new Object[] {});
}
} catch (Exception e) {
log.error(getNow() + " >任務名稱 = [" + scheduleJob.getJobName() + "]--------未啟動成功,方法名設定錯誤!!!");
}
log.info(getNow() + " >任務名稱 = [" + scheduleJob.getJobName() + "]--------啟動成功");
}
/**
* 獲取當前的時間字串 ,格式為yyyy-MM-dd HH:mm:ss.SSS
*/
private static String getNow() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
return sdf.format(new Date());
}
}
三、測試:
package cn.zzs.test;
import java.text.SimpleDateFormat;
import java.util.Date;
import cn.zzs.entity.ScheduleJob;
import cn.zzs.utils.QuartzManager;
public class MyTest {
public static void main(String[] args) {
ScheduleJob scheduleJob = new ScheduleJob();
scheduleJob.setJobName("00");
scheduleJob.setJobGroupName("TEST");
scheduleJob.setTriggerName("00");
scheduleJob.setTriggerGroupName("TEST");
scheduleJob.setBeanClass("cn.zzs.test.MyTest");
scheduleJob.setMethodName("show");
scheduleJob.setCronExpression("0/1 * * * * ?");// 每秒鐘執行一次
QuartzManager.addJob(scheduleJob);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* 測試修改任務時間
*/
scheduleJob.setCronExpression("0/30 * * * * ?");// 每30秒執行一次
QuartzManager.modifyJobTime(scheduleJob);
}
public void show() {
System.err.println(getNow());// 列印當前時間
}
private String getNow() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
return sdf.format(new Date());
}
}