(1)Job:接口,只有一个方法void execute(JobExecutionContext context),通过实现该接口来定义需要执行的任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中。
(2)JobDetail:Quartz在每次支持Job时,都重新创建一个Job实例,所以它不是直接接收一个Job实例,而是接受一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。通过JobDetail来描述Job的实现类及其他相关的静态信息,如Job名称、描述、关联监听器等信息。
(3)Trigger:描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。当仅需触发一次或者以固定间隔周期性执行时,选择SimpleTrigger,而CronTrigger则可以通过Cron表达式定义出各种复杂的调度方法。
(4)Calendar:一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。Quartz提供了若干个Calendar的实现类,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义。
(5)Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,二者在Scheduler中拥有各自的组及名称。组及名称是Scheduler查找定位容器中某一对象的依据。Scheduler可以将Trigger绑定到某一JobDetail中,这样,当Trigger被触发时,对应的Job就被执行。
(6)ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程来提高运行效率。
SimpleTrigger(String name,String group):通过构造函数指定Trigger所属组和名称。
SimpleTrigger(String name,String group,Date startTime):指定Trigger所属组、名称和触发的时间。
SimpleTrigger(String name,String group,Date startTime,Date endTime,int repeatCount,long repeatInterval):指定所属组、名称、开始时间、结束时间、重复执行次数、时间间隔。
SimpleTrigger(String name,String group,Date startTime,String jobName,String jobGroup,Date endTime,int repeatCount,long repeatInterval)在指定触发参数的同时,通过jobGroup和jobName,使该Trigger和Scheduler中的某个任务关联起来。
public class SimpleJob implements Job {
public void execute(JobExecutionContext jobCtx)
throws JobExecutionException {
System.out.println(jobCtx.getTrigger().getName()
+ " triggered. time is:" + (new Date()));
}
}
public class SimpleTriggerRunner {
public static void main(String args[]) {
try {
JobDetail jobDetail = new JobDetail("job1_1", "jgroup1",SimpleJob.class);
SimpleTrigger simpleTrigger = new SimpleTrigger("trigger1_1","tgroup1");
simpleTrigger.setStartTime(new Date());
simpleTrigger.setRepeatInterval(2000);
simpleTrigger.setRepeatCount(100);
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.scheduleJob(jobDetail, simpleTrigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(1)Cron表达式
1>星号(*):可用在所有字段中,表示对应时间域的每一个时刻。如:*在分钟字段表示每分钟。
2>问好(?):只在日期和星期字段中使用,相当于占位符。
3>减号(-):表示一个范围。如:10-12表示10点到12点
4>逗号(,):表示一个列表值。如:MON,WED,FRI表示星期一,星期但和星期五
5>斜杠(/):x/y表示一个等步长序列,x为起始值,y为增量步长值。如:5/15表示5,20,35,50。
6>L:只在日期和星期字段使用,代表Last。在日期字段中,表示这个月份的最后一天。在星期字段中,而且前面有一个数字N,则表示“这个月的最后N天”。例如:6L表示该月的最后一个星期五。
7>W:只出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15日最近的工作日。
8>LW组合:当月的最后一个工作日。
9>井号(#):只在星期字段中使用,表示当月的某个工作日。6#3表示当月的第3个星期五。
10>C:只在日期和星期字段使用,计划所关联的日期。5C在日期中表示5天后的那一天,1C在星期字段中表示星期日后的第一天。
(2)CronTrigger实例
public class CronTriggerRunner {
public static void main(String args[]) {
try {
JobDetail jobDetail = new JobDetail("job1_2", "jgroup1",
SimpleJob.class);
CronTrigger cronTrigger = new CronTrigger("trigger1_2", "tgroup1");
CronExpression cexp = new CronExpression("0/5 * * * * ?");
cronTrigger.setCronExpression(cexp);
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.scheduleJob(jobDetail, cronTrigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用Calendar把某天排除在执行程序的时间之外:
public class CalendarExample {
public static void main(String[] args) throws Exception {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
AnnualCalendar holidays = new AnnualCalendar();
//五一劳动节
Calendar laborDay = new GregorianCalendar();
laborDay.add(Calendar.MONTH,5);
laborDay.add(Calendar.DATE,1);
holidays.setDayExcluded(laborDay, true);
//国庆节
Calendar nationalDay = new GregorianCalendar();
nationalDay.add(Calendar.MONTH,10);
nationalDay.add(Calendar.DATE,1);
holidays.setDayExcluded(nationalDay, true);
scheduler.addCalendar("holidays", holidays, false, false);
//从5月1号10am开始
Date runDate = TriggerUtils.getDateOf(0,0, 10, 1, 5);
JobDetail job = new JobDetail("job1", "group1", SimpleJob.class);
SimpleTrigger trigger = new SimpleTrigger("trigger1", "group1",
runDate,
null,
SimpleTrigger.REPEAT_INDEFINITELY,
60L * 60L * 1000L);
//让Trigger遵守节日的规则(排除节日)
trigger.setCalendarName("holidays");
scheduler.scheduleJob(job, trigger);
scheduler.start();
try {
// wait 30 seconds to show jobs
Thread.sleep(30L * 1000L);
// executing...
} catch (Exception e) {
}
scheduler.shutdown(true);
}
}
当需要持久化任务调度信息,则Quartz允许用户通过调整其属性文件,将这些信息保存到数据库中。在使用数据库保存了任务调度信息后,即使系统崩溃后重新启动,任务调度信息仍将得到恢复。
(1)通过配置文件调整任务调度信息的保存策略
Quartz JAR文件的org.quartz包下包含了一个quartz。properties属性配置文件,并提供了默认设置。Quartz的属性文件主要包括:集群信息、调度器线程池、任务调度现场数据的保存。
#配置调度器的线程池
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#配置任务调度现场数据保存机制
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
默认情况下Quartz采用org.quartz.simpl.RAMJobStore保存任务的现场数据,就是保存在RAM内存中,可以通过如下设置将任务调度线程数据保存到数据库中,
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库表前缀
org.quartz.jobStore.tablePrefix = QRTZ_
#数据源名称
org.quartz.jobStore.dataSource = qzDS
#定义数据源的具体属性
org.quartz.dataSource.qzDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/sampledb
org.quartz.dataSource.qzDS.user = root
org.quartz.dataSource.qzDS.password = 123456
org.quartz.dataSource.qzDS.maxConnections = 30
(2)
从数据库中恢复任务的调度
public class JDBCJobStoreRunner {
public static void main(String args[]) {
try {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
String[] triggerGroups = scheduler.getTriggerGroupNames();//获取调度器中所有的触发器组
for (int i = 0; i < triggerGroups.length; i++) {//重新恢复在tgroup1组中名为triggerl_1的触发器的运行
String[] triggers = scheduler.getTriggerNames(triggerGroups[i]);
for (int j = 0; j < triggers.length; j++) {
Trigger tg = scheduler.getTrigger(triggers[j],triggerGroups[i]);
if (tg instanceof SimpleTrigger && tg.getFullName().equals("tgroup1.trigger1_1")) {
scheduler.rescheduleJob(triggers[j], triggerGroups[i],tg);
}
}
}
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(1)JobDetailFactoryBean
JobDetailFactoryBean扩展于Quartz的JobDetail。使用该Bean声明JobDetail时,Bean的名字即任务的名字,没有指定所属组,就使用默认组。除JobDetail中的属性,还定义了如下属性:
1>jobClass:类型为Class,实现Job接口的任务类
2>beanName:默认为Bean的id名,通过该属性显式指定Bean名称,它对应任务的名称。
3>jobDataAsMap:类型为Map,为任务所对应的JobDataMap提供值。
4>applicationContextJobDataKey:将ApplicationContext的引用保存到JobDataMap中,以便在Job的代码中访问ApplicationContext。但是只有指定一个键,用于在jobDataAsMap中保存ApplicationContext。如果不设置此键,JobDetailBean不会将ApplicationContext放入JobDataMap中。
5>jobListenerNames:类型为String[],指定注册在Scheduler中的JobListeners名称,以便让这些监听器对本任务的事件进行监听。
(2)、MethodInvokingJobDetailFactoryBean
MethodInvokingJobDetailFactoryBean可以将一个Bean的某个方法封装成满足Quartz要求的Job。如下:
concurrent属性指定任务类型。默认情况下封装为无状态的任务。如果需要封装为由状态的任务,需要将concurrent属性设置为false。通过MethodInvokingJobDetailFactoryBean产生的JobDetail不能被序列化,所以不能被持久化到数据库中。
(1)SimpleTriggerFactoryBean
SimpleTriggerFactoryBean配置的Trigger名称即为Bean的名称,属于默认组。SimpleTriggerFactoryBean中的属性有:
jobDetail:对应的JobDetail
beanName:默认为Bean的id名,对应Trigger的名称。
jobDataAsMap:以Map类型为Trigger关联的JobDataMap提供值。
startDelay:延迟多少时间开始触发,单位为毫秒,默认为0。
triggerListenerNames:类型为String[],指定注册在Scheduler中的TriggerListener名称,以便让这些监听器对本触发器的事件进行监听。
(2)CronTriggerFactoryBean
SchedulerFactoryBean的配置
org.quartz.simpl.SimpleThreadPool
10