一. 引言

1.1 简介

  • Quartz: http://www.quartz-scheduler.org/
  • 是一个 定时任务调度框架 ,比如我们遇到这样的问题
    • 想在30分钟后, 查看订单是否支付, 未支付则取消订单
    • 想在每月29号, 信用卡自动还款
    • ...
    • 想定时在某个时刻, 去做某件事情(任务)
  • Quartz是要做定时任务的调度, 设置好触发时间规则, 以及相应的任务(Job)即可

二. 使用Quartz

2.1 导入依赖

<!--quartz任务调度-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>

2.2 定义Job

package com.dz.job;

import org.quartz.*;

import java.util.Date;

//Job任务 要定时执行的某件事
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//创建工作详情
JobDetail jobDetail = jobExecutionContext.getJobDetail(); JobKey key = jobDetail.getKey();
String jobName = key.getName();//任务名
String jobGroup = key.getGroup();//任务group
System.out.println("job执行, job: " + jobName + "group: " + jobGroup + new Date());
System.out.println(new Date());
}
}

2.3 API测试

package com.dz.job;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; import java.util.Calendar;
import java.util.GregorianCalendar; public class HelloQuartz {
public static void main(String[] args) throws SchedulerException {
try {
//quartz API
//1. 调度器Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); //2. 触发器
SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")//定义name/group
.startNow()//一旦加入scheduler, 立即生效, 即开始计时
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2)//每隔两秒执行一次
.repeatForever())//一直执行, 知道结束时间
.endAt(new GregorianCalendar(2021, Calendar.MAY, 19, 23, 59, 56).getTime())//设置结束时间
.build(); //3. JobDetail
//定义Job类为HelloJob类, 这是真正的执行逻辑所在
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("job1", "group1")//定义name/group
.build(); //4. 将 任务和触发器 增加到调度器中
scheduler.scheduleJob(jobDetail,trigger); //5. 启动, 调度器开始工作
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

2.4 配置

  • 名称为: quartz.properties, 放在classpath下, 如果没有此配置则按默认配置启动
#指定调度器的名称, 非实现类
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
#指定线程池实现类
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#线程池线程数量
org.quartz.threadPool.threadCount = 10
#优先级, 默认5
org.quartz.threadPool.threadPriority = 5
#非持久化job
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

2.5 核心类说明

  • Scheduler: 调度器, 所有的调度器都是由它控制, 是Quartz的大脑, 所有任务都是由它来管理
  • Job: 任务, 想定时执行的事情(定义业务逻辑)
  • JobDetail: 基于Job, 进一步包装, 其中关联一个Job, 并为Job指定更详细的属性, 比如标识等
  • Trigger: 触发器. 可以指定给某个任务, 指定任务的触发机制

三. Trigger

3.1 SimpleTrigger

  • 以一定的时间间隔(单位是毫秒) 执行的任务

    • 指定起始和截止时间(时间段)
    • 指定时间间隔, 执行次数
  • 示例:
SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)//每秒执行一次
.repeatForever())//一直执行, 直到结束时间
.endAt(new GregorianCalendar(2021, Calendar.MAY, 19, 23, 59, 56).getTime())
.build();

SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(3)//每三分钟执行一次
.withRepeatCount(3))//执行次数不超过3次
.endAt(new GregorianCalendar(2021, Calendar.MAY, 19, 23, 59, 56).getTime())
.build();

3.2 CronTrigger [重点]

  • 适合于更复杂的任务, 它支持类型于Linux Cron的语法(并且更强大)

    • 指定Cron表达式即可
  • 示例:
//3月25当天, 每两秒执行一次
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")//定义name/group
.withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * 25 3 ?"))
.build();

//每天的10-12点, 每隔2分钟执行一次
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")//定义name/group
.withSchedule(CronScheduleBuilder.cronSchedule("0 */2 10-12 * * ?"))
.build();
3.2.1 Cron表达式组成
  • 表达式组成: "秒 分 时 日 月 星期几 [年]", 其中"年"是可选的, 一般不指定

    • 如: "10 20 18 3 5 ?"代表5月3日18点20分10秒, 星期几不确定
位置	  时间域			  允许值		特殊值
1 秒钟 0-59 ,-*/
2 分钟 0-59 ,-*/
3 小时 0-23 ,-*/
4 日期 1-31 ,-*?/LW
5 月份 1-12 ,-*/
6 星期 1-7(1为周日) ,-*?/L#
7 年份(可不写) ,-*/
3.2.2 Cron表达式符号
  • 表达式中可使用的特殊符号的含义如下
星号(*): 可用在所有字段中, 表示对应时间域的每一个时刻, 例如,在分钟字段内表示"每分钟"
问号(?): 该字段只在日期和星期字段中使用, 它通常指定为"不确定值"
减号(-): 表达一个范围, 如在小时字段中使用"10-12", 则表示从10点到12点
逗号(,): 表达一个列表值, 如在星期字段中使用"MON,WED,FRI", 则表示星期一,星期三,星期五
斜杠: x/y表达一个等步长序列, x为起始值, y为增量步长值. 如在分钟字段中使用0/15,则表示为0,15,30和45秒, 而5/15在分钟字段中表示5,20,35,50
井号(#): 该字符只用在星期字段中, "4#2"代表第2个星期三, "5#4"代表第4个星期四
L: 该字符只有在日期和星期字段中使用, 代表"Last"的意思, 但它在两个字段中的含义不同,如果L用在星期字段里, 则表示星期六,等同于7, L出现在星期字段里,而且前面有一个数值x,则表示"这个月的最后一个周x", 例如: 6L表示该月的最后星期五, L在日期字段中, 表示这个月份的最后一天, 如一月的31号, 非闰年二月的28号
W: 该字符只能出现在日期字段中, 是对前导日期的修饰, 表示离该日期最近的工作日, 例如15W表示该月15号最近的工作日, 如果该月15号是星期六, 则匹配14号的星期五; 如果15号是星期日, 则匹配16号的星期一, 如果15号是星期二, 那么结果就是15号星期二; 但要注意关联的匹配日期不能跨月
LW: 在日期字段可以组合使用LW, 它的意思是当月的最后一个工作日
3.2.3 Cron表达式示例
  • 演示示例
0 0 12 * * ?: 每天12点运行
0 15 10 * * ?: 每天10:15运行
0 15 10 * * 2020: 在2020年的每天10:15运行
0 * 14 * * ?: 每天14点到15点之间每分钟运行一次, 开始于14:00,结束于14:59
0 0/5 14 * * ?: 每天14点到15点之间每5分钟运行一次, 开始于14:00,结束于14:55
0 0/5 14,18 * * ?: 每天14点到15点之间每5分钟运行一次, 此外每天18点到19点之间也是每5分钟运行一次
0 0-5 14 * * ?: 每天14:00到14:05, 每分钟运行一次
0 0-5/2 14 * * ?: 每天14:00到14:05, 每2分钟运行一次
0 10,44 14 ? 3 4: 3月每周三的14:10和14:44, 每分钟运行一次
0 15 10 ? * 2-6: 每周一,二,三四,五的10:15运行
0 15 10 15 * ?: 每月15号10:15运行
0 15 10 L * ?: 每月最后一天10:15运行
0 15 10 ? * 6L: 每月最后一个星期五10:15运行[此时天必须是?]
0 15 10 ? * 6L 2019-2021: 在2019,2020,2021年每个月的最后一个星期五的10:15运行

四. Spring整合Quartz [重点]

4.1 导入依赖

<dependencies>
<!--quartz任务调度-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.6</version>
</dependency>
</dependencies>

4.2 定义Job

  • 定义一个Job类
package com.dz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; import java.util.Date; public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("job执行" + new Date());
}
}

4.3 配置

  • applicationContext.xml中

    • 调度器 ScheduleFactoryBean
    • 触发器 CronTriggerFactoryBean
    • JobDetail JobDetailFactoryBean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--
Spring整合Quartz进行配置遵循下面的步骤:
1. 定义工作任务的Job
2. 定义触发器Trigger, 并将触发器与工作任务绑定
3. 定义调度器, 并将Trigger注册到Scheduler
-->
<!--1. 定义任务的bean, 这里使用JobDetailFactoryBean, 也可以使用MethodInvokingJobDetailFactoryBean, 配置类似-->
<bean name="lxJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!--指定Job的名称-->
<property name="name" value="job1"/>
<!--指定Job的分组-->
<property name="group" value="job_group1"/>
<!--指定具体的Job类-->
<property name="jobClass" value="com.dz.job.MyJob"/>
</bean> <!--2. 定义触发器的bean, 定义一个Cron的Trigger, 一个触发器只能和一个任务进行绑定-->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--指定Trigger的名称-->
<property name="name" value="trigger1"/>
<!--指定Trigger的分组-->
<property name="group" value="trigger_group1"/>
<!--指定Trigger绑定的JobDetail-->
<property name="jobDetail" ref="lxJob"/>
<!--指定Cron的表达式, 当前是每隔5秒运行一次-->
<property name="cronExpression" value="*/5 * * * * ?"/>
</bean> <!--3. 定义调度器, 并将Trigger注册到调度器中-->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
<!--添加quartz配置, 如下两种方式均可-->
<!--<property name="configLocation" value="classpath:quartz.properties"/>-->
<property name="quartzProperties">
<value>
#指定调度器的名称, 实际类型为: QuartzScheduler
org.quartz.scheduler.instanceName = MyScheduler
#指定线程池实现类
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#线程池线程数量
org.quartz.threadPool.threadCount = 10
#优先级, 默认5
org.quartz.threadPool.threadPriority = 5
#不持久化job
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
</value>
</property>
</bean>
</beans>
折叠

4.4 操作

4.4.1 启动任务
  • 工厂启动, 调度器启动, 任务调度开始
public class QuartzTest {
public static void main(String[] args) throws InterruptedException, SchedulerException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
4.4.2 任务操作
4.4.2.1 删除任务
package com.dz;

import org.quartz.JobKey;
import org.quartz.SchedulerException;
import org.quartz.impl.StdScheduler;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class QuartzTest {
public static void main(String[] args) throws InterruptedException, SchedulerException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StdScheduler stdScheduler = (StdScheduler) context.getBean("scheduler");
Thread.sleep(5000);
//删除Job
stdScheduler.deleteJob(JobKey.jobKey("job1","job_group1"));
}
}
4.4.2.2 暂停, 恢复
package com.dz;

import org.quartz.JobKey;
import org.quartz.SchedulerException;
import org.quartz.impl.StdScheduler;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class QuartzTest {
public static void main(String[] args) throws InterruptedException, SchedulerException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StdScheduler stdScheduler = (StdScheduler) context.getBean("scheduler");
Thread.sleep(5000);
//暂停Job
stdScheduler.pauseJob(JobKey.jobKey("job1", "job_group1"));
Thread.sleep(5000);
//恢复Job
stdScheduler.resumeJob(JobKey.jobKey("job1","job_group1"));
}
}
4.4.2.3 批量操作
package com.dz;

import org.quartz.JobKey;
import org.quartz.SchedulerException;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class QuartzTest {
public static void main(String[] args) throws InterruptedException, SchedulerException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StdScheduler stdScheduler = (StdScheduler) context.getBean("scheduler");
Thread.sleep(5000);
GroupMatcher<JobKey> group1 = GroupMatcher.groupEquals("job_group1");
//暂停组中所有工作
stdScheduler.pauseJobs(group1);
Thread.sleep(5000);
//恢复组中所有工作
stdScheduler.resumeJobs(group1);
}
}

8_Quartz的更多相关文章

随机推荐

  1. VxWorks环境搭建与学习

    搭建环境所需的所有资源: https://pan.baidu.com/s/1sUF2I_DBHs-86IUJ4Ykn2Q 提取码: t7sj 实时系统vxWorks - Shell命令 https:/ ...

  2. Java_占位符使用

    public class t7 { public static void main(String[] args) { // TODO Auto-generated method stub //Java ...

  3. fiddler5+雷电模拟器4.0对app抓包设置

    这次项目刚好需要对微信小程序进行抓包分析,二话不说拿起手机咔咔一顿连接,发现在备用机苹果上抓包正常,但主的安卓机上证书怎么装都失败,原来安卓7版本以后对用户自行安装的证书不再信任,所以无法抓包. 因为 ...

  4. 06 app分享功能

    通过某一个点击事件触发confirm弹窗 确定后正式进行分享功能处理 这是一个封装好的分享功能插件 https://ext.dcloud.net.cn/plugin?id=4860 如果自己写的话会很 ...

  5. 云表平台VS永中office,谁更胜一筹?

    20年前,永中软件在国外办公软件独霸江山以及盗版软件肆意横行的夹缝中呱呱坠地. 经过永中人日日夜夜的不懈奋斗,永中Office V1.0面世. 永中科技 从创立之初永中软件便预见了独立创新.自主可控的 ...

  6. Linux中安装JDK详细步骤

    一.下载Linux版本的JDK 进入官网下载对应的JDK,下载之前需要先登录 官网地址 -> https://www.oracle.com/ 登录成功后,找到对应的下载位置 根据自己电脑下载对应 ...

  7. Javaweb05-Ajax

    1.基于jQuery的Ajax 1.1 基本Ajax 参数 说明 url 请求地址 type 请求类型 data 请求参数 dataType 返回参数 success 成功处理函数 error 错误处 ...

  8. java学习第一天.day04

    顺序结构 代码里没有流程控制,程序是按照书写的格式从上而下一行一行执行的, 一条语句执行完之后继续执行下一条语句,中间没有判断和跳转,直到程序的结束. 选择结构 选择结构也被称为分支结构.代码根据逻辑 ...

  9. 透过inode来理解硬链接和软链接

    什么是inode? 每个文件都对应一个唯一的inode,inode用来存储文件的元信息,包括: 对应的文件 文件字节数 文件数据块的位置 文件的inode号码 文件的硬链接数 文件的读写权限 文件的时 ...

  10. Vue3 + Socket.io + Knex + TypeScript 实现可以私聊的聊天室

    前言 下文只在介绍实现的核心代码,没有涉及到具体的实现细节,如果感兴趣可以往下看,在文章最后贴上了仓库地址.项目采用前后端模式,前端使用 Vite + Vue3 + TS:后端使用 Knex + Ex ...