Quartz
1 public void execute(JobExecutionContext context) throws JobExecutionException;
- Hello,Quartz
1 import java.util.Date; 2 import org.quartz.Job; 3 import org.quartz.JobExecutionContext; 4 import org.quartz.JobExecutionException; 5 6 public class HelloQuartzJob implements Job { 7 8 public void execute(JobExecutionContext context) 9 throws JobExecutionException { 10 System.out.println("Hello, Quartz! - executing its JOB at "+ 11 new Date() + " by " + context.getTrigger().getName()); 12 } 13 }
为了调度此任务执行,需要先得到一个Schedule实例,然后创建一个包含任务信息的JobDetail,最后创建一个Trigger管理任务的执行。
代码清单2:调度任务
1 import java.sql.Date; 2 import org.quartz.JobDetail; 3 import org.quartz.Scheduler; 4 import org.quartz.SchedulerException; 5 import org.quartz.SchedulerFactory; 6 import org.quartz.SimpleTrigger; 7 import org.quartz.impl.StdSchedulerFactory; 8 9 10 public class HelloQuartzScheduling { 11 12 public static void main(String[] args)throws SchedulerException { 13 14 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); 15 Scheduler scheduler = schedulerFactory.getScheduler(); 16 17 JobDetail jobDetail = new JobDetail("helloQuartzJob", 18 Scheduler.DEFAULT_GROUP, HelloQuartzJob.class); 19 20 SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger", 21 Scheduler.DEFAULT_GROUP); 22 23 simpleTrigger.setStartTime(new Date(System.currentTimeMillis())); 24 simpleTrigger.setRepeatInterval(5000); 25 simpleTrigger.setRepeatCount(10); 26 27 scheduler.scheduleJob(jobDetail, simpleTrigger); 28 29 scheduler.start(); 30 } 31 32 }
- CronTrigger类
位置 |
含义 |
允许的特殊字符 |
1 |
秒(0~59) |
, - * / |
2 |
分(0~59) |
, - * / |
3 |
小时(0~24) |
, - * / |
4 |
日期(1~31) |
, - * / ? L W C |
5 |
月(JAN~DEC或1~12) |
, - * / |
6 |
星期(SUN~SAT或1~7) |
, - * / ? L C # |
7 |
年(可选,1970~2099),若为空,表示全部时间范围 |
, - * / |
特殊字符 |
说明 |
* |
通配符,任意值 |
? |
无特定值。通常和其他指定的值一起使用,表示必须显示该值但不能检查 |
- |
范围。e.g.小时部分10-12表示10:00,11:00, 12:00 |
, |
列分隔符。可以让你指定一系列的值。e.g.在星期域中指定MON、TUE和WED |
/ |
增量。表示一个值的增量,e.g.分钟域中0/1表示从0开始,每次增加1min |
L |
表示Last。它在日期和星期域中表示有所不同。在日期域中,表示这个月的最后一天,而在星期域中,它永远是7(星期六)。当你希望使用星期中某一天时,L字符非常有用。e.g.星期域中6L表示每一个月的最后一个星期五 |
W |
在本月内离当天最近的工作日触发,所谓的最近工作日,即当天到工作日的前后最短距离,如果当天即为工作日,则距离是0;所谓本月内指的是不能跨月取到最近工作日,即使前/后月份的最后一天/第一天确实满足最近工作日。e.g. LW表示本月的最后一个工作日触发,W强烈依赖月份。 |
# |
表示该月的第几个星期,e.g. 1#2表示每一个月的第一个星期一 |
C |
日历值。日期值是根据一个给定的日历计算出来的。在日期域中给定一个20C将在20日(日历包括20日)或20日后日历中包含的第一天(不包括20日)激活触发器。例如在一个星期域中使用6C表示日历中星期五(日历包括星期五)或者第一天(日历不包括星期五) |
1 import java.text.ParseException; 2 import org.quartz.CronTrigger; 3 import org.quartz.JobDetail; 4 import org.quartz.Scheduler; 5 import org.quartz.SchedulerException; 6 import org.quartz.SchedulerFactory; 7 import org.quartz.impl.StdSchedulerFactory; 8 9 public class HelloQuartzScheduling { 10 11 public static void main(String[] args) 12 throws SchedulerException, ParseException { 13 14 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); 15 Scheduler scheduler = schedulerFactory.getScheduler(); 16 17 JobDetail jobDetail = new JobDetail("helloQuartzJob", 18 Scheduler.DEFAULT_GROUP, HelloQuartzJob.class); 19 20 String cronExpression = "30/5 * * * * ?"; // 每分钟的30s起,每5s触发任务 21 CronTrigger cronTrigger = new CronTrigger("cronTrigger", 22 Scheduler.DEFAULT_GROUP, cronExpression); 23 24 scheduler.scheduleJob(jobDetail, cronTrigger); 25 26 scheduler.start(); 27 } 28 29 }
CronTrigger使用HolidayCalendar类可以排除某一段时间,比如说国庆节不执行调度任务,代码示例如下:
1 import java.text.ParseException; 2 import java.util.Calendar; 3 import org.quartz.CronTrigger; 4 import org.quartz.JobDetail; 5 import org.quartz.Scheduler; 6 import org.quartz.SchedulerException; 7 import org.quartz.SchedulerFactory; 8 import org.quartz.impl.StdSchedulerFactory; 9 import org.quartz.impl.calendar.HolidayCalendar; 10 11 12 public class HelloQuartzScheduling { 13 14 public static void main(String[] args) 15 throws SchedulerException, ParseException { 16 17 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); 18 Scheduler scheduler = schedulerFactory.getScheduler(); 19 20 JobDetail jobDetail = new JobDetail("helloQuartzJob", 21 Scheduler.DEFAULT_GROUP, HelloQuartzJob.class); 22 23 Calendar cal = Calendar.getInstance(); 24 cal.set(2012, Calendar.OCTOBER, 1); // 国庆节 25 26 HolidayCalendar holidayCal = new HolidayCalendar(); 27 holidayCal.addExcludedDate(cal.getTime()); // 排除该日期 28 29 // addCalendar(String calName, Calendar calendar, 30 // boolean replace, boolean updateTriggers) 31 scheduler.addCalendar("calendar", holidayCal, true, false); 32 33 String cronExpression = "30/5 * * * * ?"; // 每5s触发任务 34 CronTrigger cronTrigger = new CronTrigger("cronTrigger", 35 Scheduler.DEFAULT_GROUP, cronExpression); 36 37 cronTrigger.setCalendarName("calendar"); 38 39 scheduler.scheduleJob(jobDetail, cronTrigger); 40 41 scheduler.start(); 42 } 43 44 }
JobStore: 任务持久化
Quartz支持任务持久化,这可以让你在运行时增加任务或者对现存的任务进行修改,并为后续任务的执行持久化这些变更和增加的部分。中心概念是JobStore接口。默认的是RAMJobStore。
上述没有用到任何的配置文件。Quartz支持配置文件,它的好处是比编写代码简单,且修改后不需要重新编译源码。
配置quartz.properties特性文件
quartz.properties文件定义了Quartz应用运行时行为,还包含了许多能控制Quartz运转的属性。它应放在工程的classpath中。
1 #============================================================================ 2 # Configure Main Scheduler Properties 3 #============================================================================ 4 5 # 实例名 6 org.quartz.scheduler.instanceName = QuartzScheduler 7 # 实例ID 8 org.quartz.scheduler.instanceId = AUTO 9 10 #============================================================================ 11 # Configure ThreadPool 12 #============================================================================ 13 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 14 # 线程个数 15 org.quartz.threadPool.threadCount = 3 16 org.quartz.threadPool.threadPriority = 5 17 18 #============================================================================ 19 # Configure JobStore 20 #============================================================================ 21 org.quartz.jobStore.misfireThreshold = 60000 22 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore 23 24 #============================================================================ 25 # Configure Plugins 26 #============================================================================ 27 org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin 28 # org.quartz.plugins.xml.JobInitializationPlugin是Quartz自带的插件, 29 # 默认时,这个插件会在 classpath 中搜索名为 quartz_jobs.xml 30 # 的文件并从中加载 Job 和 Trigger 信息 31 # v1.8之前用JobInitializationPlugin 32 #org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin 33 org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin 34 org.quartz.plugin.jobInitializer.fileNames = quartz_jobs.xml 35 org.quartz.plugin.jobInitializer.failOnFileNotFound = true 36 org.quartz.plugin.jobInitializer.scanInterval =10 37 org.quartz.plugin.jobInitializer.wrapInUserTransaction = false 38 39 # 关闭quartz新版本检测功能 40 org.quartz.scheduler.skipUpdateCheck = true
quartz从版本1.8开始,配置文件有所改动,以前quartz自带的插件是JobInitializationPlugin,而1.8中是XMLSchedulingDataProcessorPlugin. xml。
代码清单6:quartz_jobs.xml格式
1 <?xmlversion="1.0"encoding="UTF-8"?> 2 <job-scheduling-dataxmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.ogr/xml/job_scheduling_data_1_8.xsd" 5 version="1.8"> 6 <pre-processing-commands> 7 <!--在执行作业和触犯器之前执行的命令--> 8 <delete-jobs-in-group>*</delete-jobs-in-group> 9 <!--删除标示组中的所有作业,如果是“*”,则删除所有组中的作业,同时也会删除与作业有关的触犯器 --> 10 <delete-triggers-in-group>*</delete-triggers-in-group> 11 <!--删除标示组中的所有触犯器,如果是“*”,则删除所有组中的触发器 --> 12 <delete-job> 13 <!--删除指定的作业,同时也会删除与它关联的触犯器 --> 14 <name></name> 15 <group></group> 16 </delete-job> 17 <delete-trigger> 18 <!--删除指定的触犯器 --> 19 <name></name> 20 <group></group> 21 </delete-trigger> 22 </pre-processing-commands> 23 24 <processing-directives> 25 <!--在计划作业和触发器是应遵循的命令和原则 --> 26 <overwrite-existing-data>true or false</overwrite-existing-data> 27 <!--是否复写已经存在的任务计划数据,如果为false并且ingore-duplicates非false,那么文件中同名的触发器或作业将会继续存在,则会产生错误--> 28 <ignore-duplicates>true or false</ignore-duplicates> 29 <!--如果为true,计划中的任何同名的作业/触发器将会被忽略,不会产生错误--> 30 </processing-directives> 31 32 <schedule> 33 <job> 34 <name>JobName</name> 35 <group>JobGroup</group> 36 <description></description> 37 <job-class></job-class> 38 <job-listener-ref></job-listener-ref> 39 <!-- volatility,durability,recover必须按顺序设定 --> 40 <volatility></volatility> 41 <durability></durability> 42 <recover></recover> 43 <job-data-map> 44 <!-- entry可以设定多个--> 45 <entry> 46 <key></key> 47 <value></value> 48 </entry> 49 </job-data-map> 50 </job> 51 <trigger> 52 <!-- Trigger分为simple,cron,date-interval三种类型,一个trigger中只能指定一种类型--> 53 <simple> 54 <name></name> 55 <group></group> 56 <description></description> 57 <job-name></job-name> 58 <job-group></job-group> 59 <calendar-name></calendar-name> 60 <volatility></volatility> 61 <job-data-map> 62 <entry> 63 <key></key> 64 <value></value> 65 </entry> 66 </job-data-map> 67 <start-time></start-time> 68 <end-time></end-time> 69 <misfire-instruction></misfire-instruction> 70 <repeat-count></repeat-count> 71 <repeat-interval></repeat-interval> 72 </simple> 73 <cron> 74 <name></name> 75 <group></group> 76 <description></description> 77 <job-name></job-name> 78 <job-group></job-group> 79 <calendar-name></calendar-name> 80 <volatility></volatility> 81 <job-data-map> 82 <entry> 83 <key></key> 84 <value></value> 85 </entry> 86 </job-data-map> 87 <start-time></start-time> 88 <end-time></end-time> 89 <misfire-instruction></misfire-instruction> 90 <cron-expression></cron-expression> 91 <time-zone></time-zone> 92 </cron> 93 <date-interval> 94 <name></name> 95 <group></group> 96 <description></description> 97 <job-name></job-name> 98 <job-group></job-group> 99 <calendar-name></calendar-name> 100 <volatility></volatility> 101 <job-data-map> 102 <entry> 103 <key></key> 104 <value></value> 105 </entry> 106 </job-data-map> 107 <start-time></start-time> 108 <end-time></end-time> 109 <misfire-instruction></misfire-instruction> 110 <repeat-interval></repeat-interval> 111 <repeat-interval-unit></repeat-interval-unit> 112 </date-interval> 113 </trigger> 114 </schedule> 115 </job-scheduling-data>
代码清单7:quartz_jobs.xml示例
1 <?xmlversion="1.0"encoding="UTF-8"?> 2 <job-scheduling-dataxmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd" 5 version="1.8"> 6 7 <pre-processing-commands> 8 <delete-jobs-in-group>*</delete-jobs-in-group> <!-- clear all jobs in scheduler --> 9 <delete-triggers-in-group>*</delete-triggers-in-group><!-- clear all triggers in scheduler --> 10 </pre-processing-commands> 11 12 <processing-directives> 13 <overwrite-existing-data>true</overwrite-existing-data> 14 <ignore-duplicates>false</ignore-duplicates> 15 </processing-directives> 16 17 <schedule> 18 <job> 19 <name>helloQuartzJob</name> 20 <group>DEFAULT</group> 21 <description>简单的quartz使用</description> 22 <job-class>HelloQuartzJob</job-class> 23 <volatility>false</volatility> 24 <durability>true</durability> 25 <recover>false</recover> 26 </job> 27 <trigger> 28 <cron> 29 <name>trigger</name> 30 <group>DEFAULT</group> 31 <job-name>helloQuartzJob</job-name> 32 <job-group>DEFAULT</job-group> 33 <cron-expression>30/5 * * * * ?</cron-expression> 34 </cron> 35 </trigger> 36 </schedule> 37 </job-scheduling-data>
代码清单8:Quartz任务调度
1 public class HelloQuartzScheduling { 2 3 public static void main(String[] args) 4 throws SchedulerException, ParseException { 5 6 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); 7 Scheduler scheduler = schedulerFactory.getScheduler(); 8 9 scheduler.start(); 10 } 11 }
spring中的?的特殊用处:
1、如官方文档解释的那样,问号(?)的作用是指明该字段‘没有特定的值’;
2、星号(*)和其它值,比如数字,都是给该字段指明特定的值,只不过用星号(*)代表所有可能值;
3、cronExpression对日期和星期字段的处理规则是它们必须互斥,即只能且必须有一个字段有特定的值,另一个字段必须是‘没有特定的值’;
4、问号(?)就是用来对日期和星期字段做互斥的。