本章描述的是定时任务(quartz)随服务器(tomcat)启动而启动的例子。
1、web.xml的配置
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<init-param>
<param-name>config-file</param-name>
<param-value>/quartz/quartz.properties</param-value>
</init-param>
<!-- shutdown-on-unload,表示是否在卸载应用时同时停止调度,该参数推荐true,否则你的tomcat进程可能停不下来 -->
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<!-- start-scheduler-on-load,表示应用加载时就启动调度器,如果为false,则quartz.properties中指定的调度器在用户访问这个Servlet之后才会加载,在此之前,如果你通过ServletContext查找SchedulerFactory是可以找到的,但是要得到具体的Scheduler,那么你一定会发现Jvm抛出了一个NullPointerExcetion。 -->
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<!--load-on-startup是指定QuartzServlet是否随应用启动,-1表示否,正数表示随应用启动,数值越小,则优先权越高 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<init-param>
<param-name>config-file</param-name>
<param-value>/quartz/quartz.properties</param-value>
</init-param>
<!-- shutdown-on-unload,表示是否在卸载应用时同时停止调度,该参数推荐true,否则你的tomcat进程可能停不下来 -->
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<!-- start-scheduler-on-load,表示应用加载时就启动调度器,如果为false,则quartz.properties中指定的调度器在用户访问这个Servlet之后才会加载,在此之前,如果你通过ServletContext查找SchedulerFactory是可以找到的,但是要得到具体的Scheduler,那么你一定会发现Jvm抛出了一个NullPointerExcetion。 -->
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<!--load-on-startup是指定QuartzServlet是否随应用启动,-1表示否,正数表示随应用启动,数值越小,则优先权越高 -->
<load-on-startup>1</load-on-startup>
</servlet>
2、quartz.properties配置,它包含4个部分的配置,如下:
#Configure Main Scheduler Properties调度器属性(实例名和实例id)
#===============================================================
org.quartz.scheduler.instanceName = QuartzScheduler
org.quartz.scheduler.instanceId = AUTO
#===============================================================
#Configure ThreadPool线程池(threadPriority优先级最大10最小1默认5,threadCount至少1)
#===============================================================
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#===============================================================
#Configure JobStore作业存储设置
#===============================================================
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#===============================================================
#Configure Plugins插件配置
#===============================================================
org.quartz.plugin.jobInitializer.class =org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileName = /quartz/quartz_jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.validating=false
3、quartz_jobs.xml配置 xml名称上面quartz.properties中插件配置的filename
也可配置多个job
<?xml version='1.0' encoding='utf-8'?>
<quartz>
<job>
<job-detail>
<name>mainJob</name>
<group>DEFAULT</group>
<description>
MainJob
</description>
<job-class>
com.util.MainJob
</job-class>
<volatility>false</volatility>
<durability>false</durability>
<recover>false</recover>
<!--
<job-data-map allows-transient-data="true"> <entry>
<key>SCAN_DIR</key> <value>c:\quartz-book\input</value> </entry>
</job-data-map>
-->
</job-detail>
<trigger>
<simple>
<name>mainJobTrigger</name>
<group>DEFAULT</group>
<job-name>mainJob</job-name>
<job-group>DEFAULT</job-group>
<!-- <start-time>2005-06-10 6:10:00 PM</start-time> -->
<!-- repeat indefinitely every 10 seconds -->
<repeat-count>0</repeat-count>
<repeat-interval>1000</repeat-interval>
</simple>
</trigger>
</job>
</quartz>
4、创建MainJob.java
public class MainJob implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
try {
Scheduler sched = arg0.getScheduler();
this.run(sched);
} catch (Exception e) {
e.printStackTrace();
throw new JobExecutionException(e);
}
}
private void run(Scheduler sched) throws SchedulerException,
DocumentException, ClassNotFoundException, ParseException {
JdbcUtil jdbcUtil=new JdbcUtil();
String sql ="select * from JOB_TASK";
jdbcUtil.getConnection();
try {
List<Map<String, Object>> list=jdbcUtil.findResult(sql, null);
if (list != null) {
for (Map<String, Object> jobTask : list) {
sched.addJob(getJobDetail(jobTask), true);
sched.scheduleJob(getCronTrigger(jobTask));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private JobDetail getJobDetail(Map<String, Object> mapObj) throws DocumentException,
ClassNotFoundException {
JobDataMap map = new JobDataMap();
map.put("TASK_ID", Long.parseLong(mapObj.get("ID")+""));
JobDetail jobDetail = new JobDetail(mapObj.get("ID").toString(),
"AutoGroup", Class.forName(mapObj.get("CLASS_NAME").toString()));
map.put("jobTaskId", String.valueOf(mapObj.get("ID")));
map.put("taskMode", "0");
map.put("CRON_EXPRESSION", mapObj.get("CRON_EXPRESSION").toString());
jobDetail.setJobDataMap(map);
return jobDetail;
}
private CronTrigger getCronTrigger(Map<String, Object> mapObj) throws ParseException {
CronTrigger trigger = new CronTrigger(mapObj.get("ID").toString()
+ "trigger", "AutoGrouptrigger",
mapObj.get("ID").toString(), "AutoGroup", mapObj.get("CRON_EXPRESSION").toString());
return trigger;
}
}
5、在jobDetail中的实例化的类:
public class StartOne implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
JobDataMap map = arg0.getMergedJobDataMap();
System.out.println(map.get("CRON_EXPRESSION"));
}
}
二、学习quartz
1、SchedulerFactory
scheduler的生命周期是有限的,从SchedulerFactory开始直到调用它的shutdown()方法
Scheduler 工厂分别是 org.quartz.impl.DirectoSchedulerFactory 和 org.quartz.impl.StdSchedulerFactory
其中DirectoSchedulerFactory,先用静态方法 getInstance() 获取到工厂的实例,再调用其中的一个 createXXX 方法去初始化它,最后getScheduler() 方法拿到 Scheduler 的实例。
StdSchedulerFactory直接使用静态getDefaultScheduler() 方法创建 Scheduler
2、Scheduler(查询、设置 Scheduler 为 standby 模式、继续、停止)
a、开始-StdSchedulerFactory.getDefaultScheduler()初始化后就可调用start(),但不要再shutdown()后start,因为schedule的所有资源已经在shutdown是销毁了。
b、Standby 模式:导致 Scheduler 暂时停止查找 Job 去执行
c、停止 shutdonw(boolean flag) 参数true表示需要正在执行的定时任务完成之后才停止
d、rescheduleJob 恢复
a、org.quartz.Job 接口
b、通过JobExecutionContext可以得到Job 可访问到所处环境的所有信息,JobDetail,其中JobDataMap可以存储数据在jobdetail
c、有状态的 Job,实现statefuljob就行,有状态的可以保留对jobDdataMap数据的修改,有状态的使用两个jobtrigger同时调用时,一个会阻塞,等待列一个执行完成才执行
d、deleteJob可移除、interrupt可中断
3、Trigger包含 ·org.quartz.SimpleTrigger·org.quartz.CronTrigger ·org.quartz.NthIncludeDayTrigger
org.quartz.CronTrigger、org.quartz.SimpleTrigger
常用simpleTrigger、CronTrigger,其中simpleTrigger如果你需要“一次性”执行(只是在一个给定时刻执行job),或者如果你需要一个job在一个给定的时间,并让它重复N次,并在执行之间延迟T。
对CronTrigger对应的Cron表达式的格式
字段名 允许的值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日 1-31 , - * ? / L W C
月 1-12 or JAN-DEC , - * /
周几 1-7 or SUN-SAT , - * ? / L C #
年 (可选字段) empty, 1970-2099 , - * /
“?”字符:表示不确定的值
“,”字符:指定数个值
“-”字符:指定一个值的范围
“/”字符:指定一个值的增加幅度。n/m表示从n开始,每次增加m
“L”字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期X
“W”字符:指定离给定日期最近的工作日(周一到周五)
“#”字符:表示该月第几个周X。6#3表示该月第3个周五