1. 程式人生 > >quartz入門及通用型自定義定時任務框架

quartz入門及通用型自定義定時任務框架

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