本文共 14147 字,大约阅读时间需要 47 分钟。
Quartz官方网站:http://www.quartz-scheduler.org
- Quartz是一个功能非常强大的开源的作业调度框架;- 几乎可以集成任何java应用,小到单体应用,达到大型电子商务系统;- 可以用来执行成千上万的简单或者复杂的调度任务;- Quartz的任务被定义为一组标准的java组件,几乎可以执行任何编程任务;- Quartz包含了一些企业级功能:包括对JTA事务支持和集群功能;
定时发送邮件、短信通知;数据同步;
强大的调度功能;灵活的使用方式;表达式 秒 分 时 天 月 周 0 0 8 ? 5 SUN#3集群功能;
Job接口:任务;定义的任务要实现Job接口;JobDetail:对任务的描述;Trigger:触发器,可以定义任务执行时机、执行规则 - SimpleTrigger - CronTriggerScheduler:任务容器,调度器,使用触发器定义的规则去调度任务;JobStore:内存、JDBC;
引入Quartz依赖首先编写任务:HelloQuartz implements JobHelloQuartzMain - 创建JobDetail - 创建Trigger - 创建Scheduler - 启动调度 org.quartz-scheduler quartz 2.3.0
package com.etoak.quartz01;import org.quartz.Job;import org.quartz.JobExecutionContext;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;public class HelloQuartzJob implements Job { public HelloQuartzJob() { System.out.println("创建HelloQuartzJob对象"); } @Override public void execute(JobExecutionContext context) { LocalDateTime dateTime = LocalDateTime.now(); String date = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS")); System.out.println(date + "-Hello Quartz!"); }}
package com.etoak.quartz01;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;public class HelloQuartzMain { public static void main(String[] args) throws SchedulerException { // 1.创建JobDetail,使用建造者模式 JobDetail jobDetail = JobBuilder.newJob(HelloQuartzJob.class) .withIdentity("hello", "hello") .build(); // 2.创建Trigger SimpleTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("hello", "hello") .withSchedule(SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(5) // 每5秒钟执行一次 .repeatForever() ).build(); // 3.创建Scheduler Scheduler scheduler = StdSchedulerFactory .getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }}
JobDetail给Job任务传参usingJobData();
package com.etoak.quartz02;import org.quartz.*;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;public class JobDetailParamJob implements Job { private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDetail jobDetail = context.getJobDetail(); JobDataMap dataMap = jobDetail.getJobDataMap(); String first = dataMap.getString("first"); String date = LocalDateTime.now() .format(DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss")); System.out.println(date + "-first:" + first); System.out.println(date + "-second:" + id); boolean third = dataMap.getBoolean("third"); System.out.println(date + "-third:" + third); }}
package com.etoak.quartz02;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import java.text.SimpleDateFormat;import java.util.Date;// 任务两秒后执行、之后每隔三秒执行一次;// JobDetail给Job任务传参public class JobDetailParamMain { public static void main(String[] args) throws SchedulerException { JobDataMap dataMap = new JobDataMap(); dataMap.put("third", true); JobDetail jobDetail = JobBuilder.newJob(JobDetailParamJob.class) .withIdentity("param") .usingJobData("first", "第一种传参") .usingJobData("id", 100) .usingJobData(dataMap) .build(); // 创建Trigger Date current = new Date(); System.out.println( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(current)); // 获得两秒后时间 Date twoSecondsAfter = new Date(current.getTime() + 2000L); SimpleTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("param") .startAt(twoSecondsAfter) //两秒后开始执行 .withSchedule(SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(3) //之后每隔3秒执行一次 .repeatForever() ).build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }}
Trigger给Job任务传参usingJobData()
package com.etoak.quartz03;import org.quartz.*;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;public class TriggerParamJob implements Job { private Integer second; public Integer getSecond() { return second; } public void setSecond(Integer second) { this.second = second; } @Override public void execute(JobExecutionContext context) throws JobExecutionException { Trigger trigger = context.getTrigger(); JobDataMap dataMap = trigger.getJobDataMap(); String first = dataMap.getString("first"); boolean third = dataMap.getBoolean("third"); String date = LocalDateTime.now() .format(DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss")); System.out.println(date + "-first:" + first); System.out.println(date + "-second:" + second); System.out.println(date + "-third:" + third); }}
这里时间用的是LocalDateTime,传参的时候转了格式
package com.etoak.quartz03;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import java.time.LocalDateTime;import java.time.ZoneId;import java.util.Date;public class TriggerParamJobMain { public static void main(String[] args) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(TriggerParamJob.class) .withIdentity("param", "param") .build(); LocalDateTime now = LocalDateTime.now(); System.out.println("当前时间:" + now); LocalDateTime twoSecondsAfter = now.plusSeconds(2); LocalDateTime fifteenSecondsAfter = now.plusSeconds(15); Date two = Date.from(twoSecondsAfter.atZone(ZoneId.systemDefault()).toInstant()); Date fifteen = Date.from(fifteenSecondsAfter.atZone(ZoneId.systemDefault()).toInstant()); JobDataMap dataMap = new JobDataMap(); dataMap.put("third", false); SimpleTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("param") .startAt(two) .endAt(fifteen) .usingJobData("first", "第一种方式") .usingJobData("second", 2) .usingJobData(dataMap) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(3) .repeatForever() ).build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }}
合并JobDetail和Trigger的参数
package com.etoak.quartz04;import org.quartz.Job;import org.quartz.JobDataMap;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;import java.util.Map;import java.util.Set;public class MergeParamJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap dataMap = context.getMergedJobDataMap(); String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); Set> entrySet = dataMap.entrySet(); for (Map.Entry entry : entrySet) { String key = entry.getKey(); Object value = entry.getValue(); System.out.println(date + "-" + key + ':' + value); } }}
package com.etoak.quartz04;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import java.text.SimpleDateFormat;import java.util.Date;public class MegerParamMain { public static void main(String[] args) throws SchedulerException { Date current = new Date(); System.out.println( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(current)); // 获得两秒后时间 Date twoSecondsAfter = new Date(current.getTime() + 2000L); SimpleTrigger trigger = TriggerBuilder.newTrigger() .usingJobData("third", 3) .usingJobData("second", "trigger") .startAt(twoSecondsAfter) .withSchedule(SimpleScheduleBuilder .simpleSchedule().withIntervalInSeconds(3) .withRepeatCount(2) ).build(); JobDetail jobDetail = JobBuilder.newJob(MergeParamJob.class) .usingJobData("first", "first") .usingJobData("second", "JobDetail") .build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }}
上面的两次指的是第一次执行之后再执行两次。
Cron-Expressions用于配置CronTrigger的实例。Cron Expressions是由七个子表达式组成的字符串,用于描述时间的各个细节。这些子表达式用空格分隔,并表示:[秒] [分] [小时] [天] [月] [周] [年]Seconds Minutes Hours Day-of-Month Month Day-of-Week Year (optional field)时间字段 是否必填 允许值 特殊字符 秒 是 0-59 ,-*/ 分 是 0-59 ,-*/ 时 是 0-23 ,-*/ 日 是 1-31 , - * ? / L W C 月 是 1-12或者JAN-DEC ,-*/ 周 是 1-7或者SUN-SAT ,-* ? / L C # 说明:周天用1表示,依次类推 年 否 空或1970-2099 ,-*/ ,:表示或的关系 -:范围的关系【比如1-21】 *:每秒、每分、每小时等 /:每天哪个时间执行 L:用于每月,或每周,表示为每月的最后一天,或每个月的最后星期几如“6L”表示“每月的最后一个星期五” W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。 例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一; 如果15号是星期二,那结果就是15号星期二。 但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。 W字符串只能指定单一日期,而不能指定日期范围; #:是用来指定“的”每月第n个工作日,例在每周(day-of-week)这个字段中内容为"6#3" or "FRI#3" 则表示“每月第三个星期五” 表达式举例 每天14:20提醒打卡:0 20 14 ? * MON-FRI 每天1点到1点59分,每隔5分执行:0 0/5 1 * * ? 周一到周五9:00上班的时候执行:0 0 9 ? * 2-6 注意点:?只能用在"天和周" 如果有一个字段是*,那么另外一个用?; 天和周有一个确定了,另外一个就得用?;
package com.etoak.quartz05;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;import java.util.Date;public class CronJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(new Date()) + "-Hello Quartz" ); }}
package com.etoak.quartz05;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;public class CronJobMain { public static void main(String[] args) throws SchedulerException { // JobDetail JobDetail jobDetail = JobBuilder.newJob(CronJob.class) .withIdentity("cron", "cron") .build(); // Trigger CronTrigger trigger = TriggerBuilder .newTrigger() .withSchedule(CronScheduleBuilder .cronSchedule("0/5 * * * * ?") ).build(); // Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }}
org.quartz-scheduler:quartz:2.3.0org.springframework:spring-jdbc:5.0.7.RELEASEorg.springframework:spring-tx:5.0.7.RELEASEorg.springframework:spring-context-support:5.0.7.RELEASE
MethodInvokingJobDetailFactoryBean 特点:不要求任务类实现任何接口 属性:name、group、targetObject(job bean)、targetMethod(方法名)CronTriggerFactoryBean 属性:name、group、jobDetail、cronExpressionSchedulerFactoryBean 属性:triggers --> list
创建一个名称为quartz的数据库(字符集编码:utf8)创建表:执行tables_mysql_innodb.sql
org.quartz-scheduler:quartz:2.3.0org.springframework:spring-jdbc:5.0.7.RELEASEorg.springframework:spring-tx:5.0.7.RELEASEorg.springframework:spring-context-support:5.0.7.RELEASEmysql:mysql-connector-java:5.1.34
在配置SchedulerFactoryBean的时候,有个configLocation属性,指定quartz.properties文件的位置;#可以设置为任意,用在 JDBC JobStore中来唯一标识实例,但是所有集群节点中必须相同。org.quartz.scheduler.instanceName=SpringClusterTest# 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID org.quartz.scheduler.instanceId = AUTO ## 线程org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount = 10org.quartz.threadPool.threadPriority = 5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true## 存储org.quartz.jobStore.misfireThreshold = 60000#JobStoreTX,将任务持久化到数据库中。因为集群中节点依赖于数据库来传播 Scheduler实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储,不能在集群中使用 RAMJobStore。org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.tablePrefix = QRTZ_org.quartz.jobStore.maxMisfiresToHandleAtATime=10#值 true,表示 Scheduler实例要参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。org.quartz.jobStore.isClustered = true #定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。org.quartz.jobStore.clusterCheckinInterval = 5000
DataSource(HikariDataDource) 属性:driverClassName、jdbcUrl、username、passwordDataSourceTransactionManager 属性:dataSourceJobDetailFactoryBean 属性:name、group、jobClass、durability(持久化任务) 特点:要求任务继承QuartzJobBean类CronTriggerFactoryBean 属性:name、group、jobDetail、cronExpressionSchedulerFactoryBean 属性:triggers、configLocation、dataSource、transactionManager、applicationContextSchedulerContextKey(spring ioc)
转载地址:http://ixvrn.baihongyu.com/