quartz入门及通用型自定义定时任务框架

Quarta介绍

Quartz是什么

Quartz就是一个纯 Java 实现的作业调度工具,相当于数据库中的 Job、Windows 的计划任务、Unix/Linux 下的 Cron,但 Quartz 可以把排程控制的更精细.

Quartz 框架的发展历程 

Quartz项目是由James House创立的,在1998年就有该框架最初的构思,包括作业队列的概念,使用线程池来处理作业,在2001年春天在SourceForge 上创立了该项目. 

Quartz的应用场景

场景 #1: 邮件提醒和告警
场景 #2: 执行文件传输操作
场景 #3: 创建销售报表 

了解Quartz体系结构

Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的这些核心概念进行描述
Quartz 调度包的两个基本单元是作业和触发器。作业是能够调度的可执行任务,触发器提供了对作业的调度.
调度器调度器用于将与作业触发器关联,一个作业可关联多个触发器,这样每个触发器被可以触发的作业执行;一个触发器可用于控制多个作业,触发触发时,全部作业将获得调度。Quartz的调度器由Scheduler接口体现.
作业只需实现org.quartz.job接口即可.Job接口包含一个方法 execute(),execute方法体是被调度的作业体。一旦实现Job接口和execute()方法,Quartz确定作业运作的时候,它将调用 execute()方法体。
触发器SimpleTriggerCronTrigger两种类型 



通用性quartz调度框架

配置文件

pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<artifactId>learn</artifactId>
		<groupId>com.citi.learn</groupId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>..</relativePath>
	</parent>
	<artifactId>learn-quartz</artifactId>
	<name>learn-quartz</name>
	<description>learn-quartz</description>
	<properties>
		<org.springframework.version>3.2.3.RELEASE</org.springframework.version>
	</properties>
	<dependencies>
		<!-- logger -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.6.1</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.16</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>

		<!-- quartz -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.0</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.2.0</version>
		</dependency>

		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>

	</dependencies>
</project>


spring配置文件spring_commons.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/data/mongo
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
          http://www.springframework.org/schema/tx 
          http://www.springframework.org/schema/tx/spring-tx.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/util 
	      http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<context:property-placeholder location="classpath*:learn-quartz.properties" />

	<!--quartz job & schedule -->
	<bean id="quartzManager" class="com.quartz.test.QuartzManager">
		<property name="threadPriority" value="${thread.priority}" />
		<property name="threadNamePrefix" value="${thread.name.prefix}" />
		<property name="misfireThreshold" value="${misfire.threshold}" />
	</bean>

	<bean id="jobManagerStart" class="com.quartz.test.JobManagerStart"
		autowire="byName" />

	<bean id="sysJobFactory" class="com.quartz.test.baseJob.SystemJobFactory"
		autowire="byName" />

	<bean id="testJob" class="com.quartz.test.job.TestJob" autowire="byName">
		<property name="cronExpression" value="${testJob.cronExpression}" />
	</bean>

	<!--jobs -->
	<util:map id="scanJobMap" map-class="java.util.HashMap">
	<span style="background-color: rgb(51, 255, 51);"><!-- 配置在此处的job会被定时掉用,执行它的execute方法。 -->
	<!-- 所需做的只是在learn-quartz.properties中配置quartz的cron表达式,即会按照对应配置定时进行job的调用 --></span>
		<entry key="testJob" value-ref="testJob" />
	</util:map>


</beans>



示例 learn-quartz.properties文件
#quartz properties
thread.name.prefix=ThreadPool_%s
thread.priority=5
misfire.threshold=60000
howMinsAgo=30

#system job configure
#profileScanJob.cronExpression=0 0/9 * * * ?
#timeoutScanJob.cronExpression=0 0/3 * * * ?
#jobRegisterClearJob.cronExpression=0 0/19 * * * ?
<span style="background-color: rgb(51, 255, 51);">testJob.cronExpression=0/30 * * * * ?</span>


对应class

JobInfoBean.java

package com.quartz.test.baseJob;

import java.io.Serializable;
import java.util.Date;

public class JobInfoBean implements Serializable {
	private static final long serialVersionUID = 1L;
	private String fqdn;
	private String schedulerName;
	private int threadPoolSize;
	private String jobName;
	private String jobGroup;
	private String jobClassName;
	private String triggerName;
	private String triggerGroup;
	private String cronExpression;
	private String timeZoneID;
	private Date updateDt;

	public JobInfoBean() {

	}

	public String getPrimaryKey() {
		StringBuffer sb = new StringBuffer();
		sb.append(fqdn);
		sb.append(schedulerName);
		sb.append(threadPoolSize);
		sb.append(jobName);
		sb.append(jobGroup);
		sb.append(jobClassName);
		sb.append(triggerName);
		sb.append(triggerGroup);
		sb.append(cronExpression);
		sb.append(timeZoneID);
		return sb.toString();
	}

	public String getFqdn() {
		return fqdn;
	}

	public void setFqdn(String fqdn) {
		this.fqdn = fqdn;
	}

	public String getSchedulerName() {
		return schedulerName;
	}

	public void setSchedulerName(String schedulerName) {
		this.schedulerName = schedulerName;
	}

	public int getThreadPoolSize() {
		return threadPoolSize;
	}

	public void setThreadPoolSize(int threadPoolSize) {
		this.threadPoolSize = threadPoolSize;
	}

	public String getJobName() {
		return jobName;
	}

	public void setJobName(String jobName) {
		this.jobName = jobName;
	}

	public String getJobGroup() {
		return jobGroup;
	}

	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}

	public String getJobClassName() {
		return jobClassName;
	}

	public void setJobClassName(String jobClassName) {
		this.jobClassName = jobClassName;
	}

	public String getTriggerName() {
		return triggerName;
	}

	public void setTriggerName(String triggerName) {
		this.triggerName = triggerName;
	}

	public String getTriggerGroup() {
		return triggerGroup;
	}

	public void setTriggerGroup(String triggerGroup) {
		this.triggerGroup = triggerGroup;
	}

	public String getCronExpression() {
		return cronExpression;
	}

	public void setCronExpression(String cronExpression) {
		this.cronExpression = cronExpression;
	}

	public String getTimeZoneID() {
		return timeZoneID;
	}

	public void setTimeZoneID(String timeZoneID) {
		this.timeZoneID = timeZoneID;
	}

	public Date getUpdateDt() {
		return updateDt;
	}

	public void setUpdateDt(Date updateDt) {
		this.updateDt = updateDt;
	}

	@Override
	public String toString() {
		return "JobInfoBean [fqdn=" + fqdn + ", schedulerName=" + schedulerName
				+ ", threadPoolSize=" + threadPoolSize + ", jobName=" + jobName
				+ ", jobGroup=" + jobGroup + ", jobClassName=" + jobClassName
				+ ", triggerName=" + triggerName + ", triggerGroup="
				+ triggerGroup + ", cronExpression=" + cronExpression
				+ ", timeZoneID=" + timeZoneID + ", updateDt=" + updateDt + "]";
	}

}


QuartzManager.java
该class是基础工具类,负责设置线程池大小,优先级,失效时间,创建JobDetail,创建JobTrigger,创建Scheduler,并能进行  schedule job, pause schedule ,和 stop schedule .
package com.quartz.test;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.spi.JobFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.quartz.test.baseJob.JobInfoBean;
import com.quartz.test.util.QuartzUtil;

public class QuartzManager {

	static final String KEY_PK = "JobPrimaryKey";

	static {
		// skip quartz update check
		System.setProperty(StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK,
				"true");
	}
	private static Logger logger = LoggerFactory.getLogger(QuartzManager.class);
	private static final String THREAD_NAME_PREFIX = "ThreadPool_%s";
	private DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory
			.getInstance();

	private int threadPriority;
	private String threadNamePrefix;
	private long misfireThreshold;

	public int getThreadPriority() {
		return threadPriority;
	}

	public void setThreadPriority(int threadPriority) {
		this.threadPriority = threadPriority;
	}

	public String getThreadNamePrefix() {
		return threadNamePrefix;
	}

	public void setThreadNamePrefix(String threadNamePrefix) {
		this.threadNamePrefix = threadNamePrefix;
	}

	public long getMisfireThreshold() {
		return misfireThreshold;
	}

	public void setMisfireThreshold(long misfireThreshold) {
		this.misfireThreshold = misfireThreshold;
	}

	public DirectSchedulerFactory getSchedulerFactory() {
		return schedulerFactory;
	}

	public void setSchedulerFactory(DirectSchedulerFactory schedulerFactory) {
		this.schedulerFactory = schedulerFactory;
	}

	/**
	 * Schedule jobs
	 * 
	 * @param lastestJobList
	 * @throws Exception
	 */
	public void scheduleJobs(List<JobInfoBean> lastestJobList) throws Exception {
		for (JobInfoBean jobInfo : lastestJobList) {
			this.scheduleJob(jobInfo);
		}
	}

	/**
	 * Schedule jobs with specific JobFactory
	 * 
	 * @param lastestJobList
	 * @param jobFactory
	 * @throws Exception
	 */
	public void scheduleJobs(List<JobInfoBean> lastestJobList,
			JobFactory jobFactory) throws Exception {
		for (JobInfoBean jobInfo : lastestJobList) {
			this.scheduleJob(jobInfo, jobFactory);
		}
	}

	/**
	 * schedule a job using default JobFacotry
	 * 
	 * @param jobInfo
	 * @param rptInfo
	 * @throws Exception
	 */
	public void scheduleJob(JobInfoBean jobInfo) throws Exception {
		this.scheduleJob(jobInfo, null);
	}

	/**
	 * schedule a job using custom JobFacotry
	 * 
	 * @param jobInfo
	 * @param rptInfo
	 * @param jobFactory
	 * @throws Exception
	 */
	public void scheduleJob(JobInfoBean jobInfo, JobFactory jobFactory)
			throws Exception {

		Scheduler quartzScheduler = this.getScheduler(jobInfo, jobFactory);

		if (quartzScheduler.checkExists(new JobKey(jobInfo.getJobName(),
				jobInfo.getJobGroup()))) {
			logger.info(String.format("Job [%s] already exists",
					jobInfo.getJobName()));
		} else {
			// Job Details
			JobDetail job = this.getJobDetail(quartzScheduler, jobInfo);

			// Cron Trigger
			Trigger trigger = this.getJobTrigger(quartzScheduler, jobInfo);

			// Tell quartz to schedule the job using our trigger
			quartzScheduler.scheduleJob(job, trigger);

			logger.info(String.format(
					"Job [%s], Frequency [%s] has been scheduled.",
					jobInfo.getJobName(), jobInfo.getCronExpression()));
		}
	}

	/**
	 * unSchedule jobs and stop all no job schedulers
	 * 
	 * @param lastestJobList
	 * @throws Exception
	 */
	public void unscheduleJobs(List<JobInfoBean> lastestJobList)
			throws Exception {
		for (JobInfoBean jobInfo : lastestJobList) {
			this.unScheduleJob(jobInfo);
		}

		this.stopAllNoJobScheduler();
	}

	/**
	 * unSchedule a job
	 * 
	 * @param jobInfo
	 * @throws Exception
	 */
	public void unScheduleJob(JobInfoBean jobInfo) throws Exception {
		Scheduler quartzScheduler = schedulerFactory.getScheduler(jobInfo
				.getSchedulerName());
		JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());

		if (null == quartzScheduler) {
			throw new Exception(String.format(
					"unSchedule Job %s the Scheduler %s does not exists!",
					jobInfo.getJobName(), jobInfo.getSchedulerName()));
		}

		if (quartzScheduler.checkExists(jobKey)) {
			if (quartzScheduler.deleteJob(jobKey)) {
				logger.info(String.format("unSchedule Job successfully!\r\n%s",
						jobInfo.toString()));
			} else {
				throw new Exception(String.format(
						"unSchedule Job failed!\r\n%s", jobInfo.toString()));
			}
		} else {
			logger.warn(String.format("unSchedule Job does not exists!\r\n%s",
					jobInfo.toString()));
		}
	}

	/**
	 * get scheduler if not exists will create it
	 * 
	 * @param jobInfo
	 * @return
	 * @throws SchedulerException
	 */
	public Scheduler getScheduler(JobInfoBean jobInfo, JobFactory jobFactory)
			throws SchedulerException {
		Scheduler scheduler = schedulerFactory.getScheduler(jobInfo
				.getSchedulerName());
		if (null == scheduler) {
			this.createScheduler(jobInfo);
			scheduler = schedulerFactory.getScheduler(jobInfo
					.getSchedulerName());
			// using custom instead of SimpleJobFactory
			if (null != jobFactory) {
				scheduler.setJobFactory(jobFactory);
			}
		}

		return scheduler;
	}

	/**
	 * create the scheduler
	 * 
	 * @param jobInfo
	 * @throws SchedulerException
	 */
	private void createScheduler(JobInfoBean jobInfo) throws SchedulerException {
		String schedulerName = jobInfo.getSchedulerName();
		String schedulerInstanceId = jobInfo.getSchedulerName();

		SimpleThreadPool threadPool = new SimpleThreadPool(
				jobInfo.getThreadPoolSize(), threadPriority);

		this.threadNamePrefix = StringUtils.defaultIfEmpty(threadNamePrefix,
				THREAD_NAME_PREFIX);
		threadPool.setThreadNamePrefix(String.format(threadNamePrefix,
				jobInfo.getSchedulerName()));

		RAMJobStore jobStore = new RAMJobStore();
		jobStore.setMisfireThreshold(misfireThreshold);

		schedulerFactory.createScheduler(schedulerName, schedulerInstanceId,
				threadPool, jobStore);
	}

	/**
	 * get job details if not exists will create it
	 * 
	 * @param quartzScheduler
	 * @param jobInfo
	 * @param plannerInfo
	 * @param rptInfo
	 * @return
	 * @throws Exception
	 */
	public JobDetail getJobDetail(Scheduler quartzScheduler, JobInfoBean jobInfo)
			throws Exception {
		JobDetail jobDetail = this.getJobDetailFromScheduler(quartzScheduler,
				jobInfo.getJobName(), jobInfo.getJobGroup());

		if (null == jobDetail) {
			jobDetail = this.createJobDetail(jobInfo);
		}

		return jobDetail;
	}

	/**
	 * Get JobDetail from Scheduler by job name and job group
	 * 
	 * @param scheduler
	 * @param jobName
	 * @param jobGroup
	 * @return
	 * @throws SchedulerException
	 */
	public JobDetail getJobDetailFromScheduler(Scheduler scheduler,
			String jobName, String jobGroup) throws SchedulerException {
		JobKey jobKey = new JobKey(jobName, jobGroup);
		return scheduler.getJobDetail(jobKey);
	}

	/**
	 * Create a Job Details
	 * 
	 * @param jobInfo
	 * @param plannerInfo
	 * @param rptInfo
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private JobDetail createJobDetail(JobInfoBean jobInfo) throws Exception {
		JobDetailImpl job = new JobDetailImpl();
		job.setJobClass((Class<? extends Job>) Class.forName(jobInfo
				.getJobClassName()));
		job.setDescription(null);
		job.setKey(new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup()));
		job.setDurability(false);
		job.setRequestsRecovery(false);

		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put(KEY_PK, jobInfo.getPrimaryKey());
		job.setJobDataMap(jobDataMap);

		return job;
	}

	/**
	 * if Trigger is created in Scheduler, will return it directly, or create
	 * it.
	 * 
	 * @param jobInfo
	 * @return
	 * @throws ParseException
	 * @throws SchedulerException
	 */
	public Trigger getJobTrigger(Scheduler quartzScheduler, JobInfoBean jobInfo)
			throws ParseException, SchedulerException {
		Trigger trigger = null;

		TriggerKey triggerKey = new TriggerKey(jobInfo.getTriggerName(),
				jobInfo.getTriggerGroup());
		trigger = quartzScheduler.getTrigger(triggerKey);

		if (null == trigger) {
			trigger = this.createTrigger(jobInfo);
		}

		return trigger;
	}

	/**
	 * create trigger
	 * 
	 * @param jobInfo
	 * @return
	 * @throws ParseException
	 */
	private Trigger createTrigger(JobInfoBean jobInfo) throws ParseException {
		CronTriggerImpl trigger = new CronTriggerImpl();
		trigger.setTimeZone(QuartzUtil.getTimeZone(jobInfo.getTimeZoneID()));
		trigger.setName(jobInfo.getTriggerName());
		trigger.setGroup(jobInfo.getTriggerGroup());
		trigger.setCronExpression(jobInfo.getCronExpression());

		return trigger;
	}

	/**
	 * Start all Schedulers
	 * 
	 * @throws Exception
	 */
	public void startAllScheduler() throws Exception {
		String returnMsg = null;

		Collection<Scheduler> allScheduler = schedulerFactory
				.getAllSchedulers();
		for (Scheduler scheduler : allScheduler) {
			returnMsg = this.start(scheduler);
			logger.info(returnMsg);
		}
	}

	/**
	 * Stop all Schedulers
	 * 
	 * @throws Exception
	 */
	public void stopAllScheduler() throws Exception {
		String returnMsg = null;

		Collection<Scheduler> allScheduler = schedulerFactory
				.getAllSchedulers();
		for (Scheduler scheduler : allScheduler) {
			returnMsg = this.stop(scheduler);
			logger.info(returnMsg);
		}
	}

	/**
	 * Pause all Schedulers
	 * 
	 * @throws Exception
	 */
	public void pauseAllScheduler() throws Exception {
		String returnMsg = null;

		Collection<Scheduler> allScheduler = schedulerFactory
				.getAllSchedulers();
		for (Scheduler scheduler : allScheduler) {
			returnMsg = this.pause(scheduler);
			logger.info(returnMsg);
		}
	}

	/**
	 * Stop all no job Scheduler
	 * 
	 * @throws Exception
	 */
	public void stopAllNoJobScheduler() throws Exception {
		List<Scheduler> needStopSchedulerList = new ArrayList<Scheduler>();
		// need stop the scheduler in another List, or will get
		// ConcurrentModificationException
		Collection<Scheduler> allScheduler = schedulerFactory
				.getAllSchedulers();
		for (Scheduler scheduler : allScheduler) {
			if (scheduler.getJobGroupNames().isEmpty()) {
				needStopSchedulerList.add(scheduler);
			}
		}

		for (Scheduler scheduler : needStopSchedulerList) {
			this.stop(scheduler);
			logger.info(String
					.format("Scheduler %s has been stoped, because it has no any job already.",
							scheduler.getSchedulerName()));
		}
	}

	/**
	 * Shutdown Scheduler by name
	 * 
	 * @param schedName
	 * @throws SchedulerException
	 */
	public void shutdownSchedByName(String schedName) throws SchedulerException {
		schedulerFactory.getScheduler(schedName).shutdown(true);
	}

	/**
	 * Stop Scheduler
	 * 
	 * @param quartzScheduler
	 * @return
	 * @throws SchedulerException
	 */
	public String stop(Scheduler quartzScheduler) throws SchedulerException {
		String returnMsg = "";
		if (!quartzScheduler.isStarted()) {
			returnMsg = String.format("%s is not started!",
					quartzScheduler.getSchedulerName());
		} else if (quartzScheduler.isShutdown()) {
			returnMsg = String.format("%s already stoped!",
					quartzScheduler.getSchedulerName());
		} else {
			// waiting all job complete
			quartzScheduler.shutdown(true);
			returnMsg = String.format("Stop %s successfully!",
					quartzScheduler.getSchedulerName());
		}

		return returnMsg;
	}

	/**
	 * Start Scheduler
	 * 
	 * @param quartzScheduler
	 * @return
	 * @throws Exception
	 */
	public String start(Scheduler quartzScheduler) throws Exception {
		String returnMsg = "";
		if (quartzScheduler.isShutdown()) {
			quartzScheduler.start();
			returnMsg = String.format(
					"start %s from shutdown status successfully!",
					quartzScheduler.getSchedulerName());
		} else if (quartzScheduler.isStarted()
				&& quartzScheduler.isInStandbyMode()) {
			quartzScheduler.start();
			returnMsg = String.format(
					"start %s from paused status successfully!",
					quartzScheduler.getSchedulerName());
		} else if (quartzScheduler.isStarted()) {
			returnMsg = String.format("%s already be started!",
					quartzScheduler.getSchedulerName());
		} else {
			quartzScheduler.start();
			returnMsg = String.format("Start %s successfully!",
					quartzScheduler.getSchedulerName());
		}

		return returnMsg;
	}

	/**
	 * Pause Scheduler
	 * 
	 * @param quartzScheduler
	 * @return
	 * @throws SchedulerException
	 */
	public String pause(Scheduler quartzScheduler) throws SchedulerException {
		String returnMsg = "";
		if (!quartzScheduler.isStarted()) {
			returnMsg = String.format(
					"%s is not started, please start it first!",
					quartzScheduler.getSchedulerName());
		} else if (quartzScheduler.isShutdown()) {
			returnMsg = String.format("%s is shutdown, please start it first!",
					quartzScheduler.getSchedulerName());
		} else if (quartzScheduler.isInStandbyMode()) {
			returnMsg = String.format("%s is already be paused!",
					quartzScheduler.getSchedulerName());
		} else {
			quartzScheduler.standby();
			returnMsg = String.format("Paused %s Successfully",
					quartzScheduler.getSchedulerName());
		}

		return returnMsg;
	}
}


JobManagerStart.java
该类进行所有job启动的入口,持有一个quartzManager对象,根据spring 注入的sysJobFactory,遍历扫描配置在其中的job,根据job的信息创建JobInfoBean对象,并转化为quartz的job对象,通过quartzManager,schedule该job
package com.quartz.test;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.quartz.test.baseJob.JobInfoBean;
import com.quartz.test.baseJob.SystemJob;
import com.quartz.test.baseJob.SystemJobFactory;

public class JobManagerStart {
	
	private static Logger logger = LoggerFactory.getLogger(JobManagerStart.class);
	private static final String SYS_JOB_SCHEDULERNAME = "SCHEDULER_SYS";
	private static final String SYS_JOB_JOBGROUPNAME = "JOBGROUP_SYS";
	private static final String SYS_JOB_TRIGGERGROUPNAME = "TRIGGERGROUP_SYS";
	private static final String SYS_JOB_TRIGGERNAME_PATTERN = "TRIGGER_%s";
	
	private SystemJobFactory sysJobFactory;
	private QuartzManager quartzManager;
	private int sysJobCount;
	
	public SystemJobFactory getSysJobFactory() {
		return sysJobFactory;
	}

	public void setSysJobFactory(SystemJobFactory sysJobFactory) {
		this.sysJobFactory = sysJobFactory;
	}

	public QuartzManager getQuartzManager() {
		return quartzManager;
	}

	public void setQuartzManager(QuartzManager quartzManager) {
		this.quartzManager = quartzManager;
	}

	public int getSysJobCount() {
		return sysJobCount;
	}

	public void setSysJobCount(int sysJobCount) {
		this.sysJobCount = sysJobCount;
	}

	/**
	 * Initial All Quartz Job which configured at database and System Scan Jobs
	 * 
	 * @throws Exception
	 */
	public void initQuartzJob() throws Exception{
		scheduleSysScanJob();
		quartzManager.startAllScheduler();
	}
	
	
	/**
	 * Schedule System Scan Job
	 * 
	 * @throws Exception
	 */
	private void scheduleSysScanJob() throws Exception {
		Map<String, SystemJob> scanJobMap = sysJobFactory.getScanJobMap();
		this.sysJobCount = scanJobMap.size();

		Iterator<Entry<String, SystemJob>> iterator = scanJobMap.entrySet().iterator();
		while (iterator.hasNext()) {
			Entry<String, SystemJob> entry = iterator.next();

			JobInfoBean jobInfo = populateJobInfo(entry.getKey(), entry.getValue());
			logger.info(String.format("initial system scan job [%s] frequency [%s]", jobInfo.getJobName(),
					jobInfo.getCronExpression()));
			quartzManager.scheduleJob(jobInfo, sysJobFactory);
		}
	}
	
	/**
	 * Populate JobInfoBean
	 * 
	 * @param jobName
	 * @param scanJob
	 * @param threadPoolSize
	 * @return
	 */
	private JobInfoBean populateJobInfo(String jobName, SystemJob scanJob) {
		JobInfoBean jobInfo = new JobInfoBean();
		jobInfo.setSchedulerName(SYS_JOB_SCHEDULERNAME);
		jobInfo.setJobClassName(scanJob.getClass().getName());
		jobInfo.setJobName(jobName);
		jobInfo.setJobGroup(SYS_JOB_JOBGROUPNAME);
		jobInfo.setTriggerName(String.format(SYS_JOB_TRIGGERNAME_PATTERN, jobName));
		jobInfo.setTriggerGroup(SYS_JOB_TRIGGERGROUPNAME);
		jobInfo.setCronExpression(scanJob.getCronExpression());
		jobInfo.setTimeZoneID(null);
		jobInfo.setThreadPoolSize(sysJobCount);

		return jobInfo;
	}
	
	/**
	 * Shutdown All Schedulers
	 * 
	 * @throws Exception
	 */
	public void shutdown() throws Exception {
		logger.info("Shutdown all schedulers begin ...");
		quartzManager.stopAllScheduler();
		logger.info("Shutdown all schedulers sucessfully!");
	}
}


SystemJobFactory.java

存放job的地方,job放到scanJobMap,可以通过spring注入

package com.quartz.test.baseJob;

import java.util.Map;

import org.quartz.Job;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.simpl.SimpleJobFactory;
import org.quartz.spi.TriggerFiredBundle;

public class SystemJobFactory extends SimpleJobFactory {
	private Map<String, SystemJob> scanJobMap;

	public Map<String, SystemJob> getScanJobMap() {
		return scanJobMap;
	}

	public void setScanJobMap(Map<String, SystemJob> scanJobMap) {
		this.scanJobMap = scanJobMap;
	}

	public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
		SystemJob job = scanJobMap.get(bundle.getJobDetail().getKey().getName());
		// must reset interrupt indicate
		job.setInterrupted(false);
		return job;
	}
}



其它工具类
QuartzUtil.java
package com.quartz.test.util;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuartzUtil {
	private static Logger logger = LoggerFactory.getLogger(QuartzUtil.class);
	public static final String SCHEDULER_NAME_PATTERN = "SCHEDULER_%s";
	public static final String JOB_NAME_PATTERN = "JOB_%s";
	public static final String JOB_GROUP_PATTERN = "JOBGROUP_%s";
	public static final String TRIGGER_NAME_PATTERN = "TRIGGER_%s";
	public static final String TRIGGER_GROUP_PATTERN = "TRIGGERGROUP_%s";

	/**
	 * Get Scheduler Name
	 * 
	 * @param key
	 * @return
	 */
	public static String getSchedulerName(String key) {
		return String.format(SCHEDULER_NAME_PATTERN, key);
	}

	/**
	 * Get Job Name
	 * 
	 * @param key
	 * @return
	 */
	public static String getJobName(String key) {
		return String.format(JOB_NAME_PATTERN, key);
	}

	/**
	 * Get Job Group Name
	 * 
	 * @param key
	 * @return
	 */
	public static String getJobGroupName(String key) {
		return String.format(JOB_GROUP_PATTERN, key);
	}

	/**
	 * Get Trigger Name
	 * 
	 * @param key
	 * @return
	 */
	public static String getTriggerName(String key) {
		return String.format(TRIGGER_NAME_PATTERN, key);
	}

	/**
	 * Get Trigger Group Name
	 * 
	 * @param key
	 * @return
	 */
	public static String getTriggerGroupName(String key) {
		return String.format(TRIGGER_GROUP_PATTERN, key);
	}

	/**
	 * Get TimeZone Object by give ID, if timeZoneID is null or not exists will
	 * return current OS timezone
	 * 
	 * @param timeZoneID
	 * @return
	 */
	public static TimeZone getTimeZone(String timeZoneID) {
		TimeZone timeZone = TimeZone.getDefault();
		if (StringUtils.isNotBlank(timeZoneID)) {
			String[] availableIDs = TimeZone.getAvailableIDs();
			for (String availableID : availableIDs) {
				if (availableID.equals(timeZoneID)) {
					logger.info(String.format(
							"timeZoneID [%s] is configured and valid",
							timeZoneID));
					timeZone = TimeZone.getTimeZone(timeZoneID);
					break;
				}
			}
		}
		return timeZone;
	}

	/**
	 * Get Quartz Scheduler ThreadPool Size, if profile size greater than
	 * default size, it will return default size, or will return profile size
	 * 
	 * @param profileSize
	 * @param defaultThreadPoolSize
	 * @return
	 * @throws Exception
	 */
	public static int getThreadPoolSize(int profileSize, int defaultSize)
			throws Exception {
		if (profileSize < 0) {
			throw new Exception(String.format(
					"Your profileSize is %s, it cannot be negative number!",
					profileSize));
		}

		return profileSize < defaultSize ? profileSize : defaultSize;
	}
}

BaseJob.java
package com.quartz.test.baseJob;

import org.quartz.InterruptableJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.UnableToInterruptJobException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class BaseJob implements InterruptableJob {
	private static Logger logger = LoggerFactory.getLogger(BaseJob.class);
	private boolean interrupted;

	@Override
	public abstract void execute(JobExecutionContext context)
			throws JobExecutionException;

	@Override
	public void interrupt() throws UnableToInterruptJobException {
		interrupted = true;
		logger.info(String.format("Job %s has been interrupted!", this
				.getClass().getName()));
	}

	public boolean isInterrupted() {
		return interrupted;
	}

	public void setInterrupted(boolean interrupted) {
		this.interrupted = interrupted;
	}

}

SystemJob.java
package com.quartz.test.baseJob;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;


public abstract class SystemJob extends BaseJob {
	private String cronExpression;

	@Override
	public abstract void execute(JobExecutionContext context)
			throws JobExecutionException;

	public String getCronExpression() {
		return cronExpression;
	}

	public void setCronExpression(String cronExpression) {
		this.cronExpression = cronExpression;
	}

}


测试类,例:配置一个TestJob,让spring注入到SystemJobFactory
TestJob.java
package com.quartz.test.job;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import com.quartz.test.baseJob.SystemJob;

public class TestJob extends SystemJob {

	@Override
	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		// TODO Auto-generated method stub
		System.out
				.println("This is a test job.what you have to do is just to implement your own logic here ...");
	}

}



测试入口
TestQuartzClient.java
package com.quartz.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestQuartzClient {

	private static Logger logger = LoggerFactory
			.getLogger(TestQuartzClient.class);
	private JobManagerStart jobManagerStart;

	public void startJob() throws Exception {
		logger.info("method start...");
		ApplicationContext ctx = new ClassPathXmlApplicationContext(
				"spring_commons.xml");
		jobManagerStart = (JobManagerStart) ctx.getBean("jobManagerStart");
		jobManagerStart.initQuartzJob();
		logger.info("method end...");
	}

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		new TestQuartzClient().startJob();
	}

}


整个流程分析:

首先:TestQuartzClient启动,spring初始化配置文件中的bean。 然后,取得jobManagerStart对象,jobManagerStart.initQuartzJob() ,分为两个动作.
1.populateJobInfo:扫描注入的sysJobFactory配置的job,转化为jobinfobean对象(jobinfobean基本配置设置为常用定值,其中scanJob.getCronExpression()是根据spring读取learn-quartz.properties中的值注入的) 。
2.quartzManager.scheduleJob(jobInfo, sysJobFactory): 通过持有的quartzManager对象,将上一步转化好的jobinfo,进行schedule。

通用型:实现者只需继承SystemJob,在自己类中的execute方法中编写自己的实现逻辑,再在properties文件中配置需要按怎样的定时逻辑执行即可。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值