quartz入门及通用型自定义定时任务框架
一 Quarta介绍1 Quartz是什么Quartz就是一个纯 Java 实现的作业调度工具,相当于数据库中的 Job、Windows 的计划任务、Unix/Linux 下的 Cron,但 Quartz 可以把排程控制的更精细.2 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()方法体。
触发器:有SimpleTrigger和CronTrigger两种类型
通用性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文件中配置需要按怎样的定时逻辑执行即可。
更多推荐
已为社区贡献1条内容
所有评论(0)