1. 程式人生 > >quartz定時器的使用,定時任務的動態增刪改

quartz定時器的使用,定時任務的動態增刪改

目錄

一、簡介:

二、使用:

三、測試:

一、簡介:

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());
	}
}