Quartz框架
简介:一个开源的作业调度框架,比较简单灵活。它可以使用在web工程中,也可以在java简单工程中直接使用。
spring框架中也整合了此框架,org.springframework.scheduling.quartz
1、主要API
- Job:作业,任务具体实现
- JobDetail:作业细节,制定作业名等
- Trigger:触发器,定义作业触发时间
- scheduler:任务调度器
2、配置maven
引入quartz框架的jar包
<!-- quartz 框架 自动任务调度 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
如果还有使用spring整合quartz框架配置方式,则还要引入上下文支持:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
3、简单实例
quartz框架的实现可以直接编程式,也可以整合spring配置方式实现。
- 编程式实现
- 配置式实现
3.1、编程式实现
3.1.1、Job类
通过实现org.quartz.Job接口
package com.wm.spring.quartz;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MyJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//context 是作业调度上下文,可以从中获取作业细节名、触发器名等信息
JobDetail jobDetail = context.getJobDetail();
//作业名
String name = jobDetail.getKey().getName();
// 触发器名
String triggerName = context.getTrigger().getKey().getName();
System.out.println("jobDetail.getKey().getName: "+name);
System.out.println("context.getTrigger().getKey().getName: "+triggerName);
System.out.println("MyJob ....... " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
实现Job接口,编写public void execute(JobExecutionContext context)方法。
在启动Job时,它会自动运行execute方法。
3.1.2、简单的测试
3.1.2.1、简单的触发器
simpleSchedule
package com.wm.spring.quartz;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.quartz.Scheduler;
import org.quartz.impl.StdSchedulerFactory;
import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
public class SimpleScheduler {
public static void main(String[] args) throws Exception {
// 获取 作业调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 定义 作用细节
JobDetail job = newJob(MyJob.class)
.withIdentity("job1", "group1")
.build();
// 定义 触发器
Trigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.startNow() // 现在运行
.withSchedule(simpleSchedule() // 定义调度器
.withIntervalInSeconds(10) //定义 循环时间 每10S运行一次
.repeatForever()) // 永远重复
.build();
scheduler.scheduleJob(job, trigger); // 注册作用 和 调度器
scheduler.start(); // 任务调度器 开启
}
}
3.1.2.2、cron触发器
cronSchedule
// 定义 作用细节
JobDetail job2 = newJob(MyJob.class)
.withIdentity("job2", "group2")
.build();
Trigger trigger2 = newTrigger()
.withIdentity("trigger2", "group2")
.startNow()
.withSchedule(cronSchedule("0/5 * * * * ?")) // cron 表达式
.build();
scheduler.scheduleJob(job2, trigger2); // 注册作用 和 调度器
scheduler.start(); // 任务调度器 开启
3.1.2.3、结果
简单触发器:
job 每隔10s运行一次
cron触发器
job2 每隔5s触发一次
3.1.3、注意
在使用编程式实现时,如果发现newTrigger()、newJob(class) 、simpleSchedule()、cronSchedule()等静态方法不能使用时,则是因为 没有导入 静态包
import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
一定要导入静态包,否则不能实现。
是因为 quartz框架2.x以后版本都是使用这种方法,它把实现触发器和作业细节都使用静态方式来的
如果你是使用的1.x,则不存在这个问题,并且获取的方式都不是使用这种静态方法的方式,而是直接可以new出来。
3.2、配置式方式
在spring容器中进行整合quartz框架
3.2.1、配置文件
spring-quartz.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">
<bean id="myJob" class="com.wm.spring.quartz.MyJob" />
<!-- 定义 作业细节 Job Detail -->
<bean id="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 注入 Job 作业 -->
<property name="jobClass" value="com.wm.spring.quartz.MyJob" />
<property name="durability" value="true" />
</bean>
<!-- 定义 简单触发器 -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<!-- 注入 作业细节 JobDetail -->
<property name="jobDetail" ref="myJobDetail" />
<!-- 设置重复时间 2000ms -->
<property name="repeatInterval" value="2000" />
<!-- 设置 开始延迟时间 -->
<property name="startDelay" value="0" />
</bean>
<!-- 定义 cron 触发器-->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 定义作业细节 -->
<property name="jobDetail" ref="myJobDetail" />
<!-- 定义 cron 表达式 (秒 分 时 日 月 周 年) -->
<property name="cronExpression" value="0/5 * * * * ?" />
</bean>
<!-- 定义 任务调度器工厂 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 绑定触发器 -->
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
<ref bean="simpleTrigger"/>
</list>
</property>
</bean>
</beans>
这里面配置了两种方式:简单触发器、cron触发器。
在加载配置文件时,作业调度器就会自动启动,并且根据触发器的触发时间去调用Job作业里具体的实现。
注:如果提示:SchedulerFactoryBean、CronTriggerFactoryBean、SimpleTriggerFactoryBean、JobDetailFactoryBean等,这些无法实现,则说明是因为spring框架中没有加入上下文支持jar
Maven pom.xml配置如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
3.2.2、测试类
QuartzMainTest.java
package com.wm.spring.TEST;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class QuartzMainTest {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("spring-quartz.xml");
}
}
在加载配置文件后,任务调度器就会自动启动,再根据触发器配置的触发时间 去执行 作业。
3.2.3、结果
simpleTrigger:每隔2000ms(2s)执行一次
cronTrigger : 每隔5s执行一次
4、CronExpression
cron表达式包括7个字段:
(秒 分 时 日 月 周 年)
- 秒 (0~59) -,*,/
- 分 (0~59) -,*,/
- 时 (0~23) -,*,/
- 日 (0~31) -,*,/,?,L,W,C
- 月 (1~12) -,*,/,(JAN~DEC)
- 周/星期 (1~7),-,*,/,?,(SUN~SAT),L,C
- 年 (可选)1970~2099 -,*,/
4.1、特殊符号
-,*,/,?,,,W,C,L,#
4.1.1、星号(*)
使用星号(*) 指示着你想在这个域上包含所有合法的值。
如: (* 30 2 * * ?),表示:每一天的2点30分-31分之间的每一秒都运行一次
4.1.2、中划线(-)
中划线 (-) 用于指定一个范围。
如:(0 30-33 2 * * ?),表示: 每一天的2点30、31、32、33分的时候执行
4.1.3、反斜线(/)
斜杠 (/) 是用于时间表的递增的。n/m表示从n开始,每次增加m
如:(0/2 * * * * ?),表示:每隔两秒运行一次
(0 0/5 * * * ?),表示:每隔五分钟运行一次
4.1.4、问号(?)
? 号只能用在日和周域上,但是不能在这两个域上同时使用,表示不确定的值。
它不同于星号,星号是指示着该域上的每一个值。? 是说不为该域指定值。
它不能在日和周域上同时指定的原因是 容易引起模拟两可的意义。
如:如果在日域上是3,在周域上是3,那它表示是什么呢?是每个月的3号又刚好是星期二??还是说每周二的3号执行?
所以要排除这种不明确的可能性。
只要记住,假如你为这两域的其中一个指定了值,那就必须在另一个字值上放一个 ?。
如:(0 13 2 1 * ?),表示:每个月的1号的2:13执行
(0 13 2 ? * 3),表示:每周二的2:13执行
4.1.5、井号(#)
表示该月第几个周X,只能用于周域。6#3表示该月第3个周五
如:(0 30 2 ? * 4#2),表示这个月的第二个周三的2:30执行
4.1.6、逗号(,)
逗号 (,) 是用来在给某个域上指定一个值列表的。
如:(0 30 2,3,4 ? * *),表示:每天的2:30、3:30、4:30的时候执行
4.1.7、字母(L、W、C)
字母L
在日表示一个月中的最后一天,用在周表示该月最后一个星期X
如:(0 30 4 L * ?),表示:每一个月的最后一天的4:30执行
(0 30 4 ? * L),表示:每一个月的最后一个星期六的4:30执行
(0 30 4 ? * 3L),表示:每月的最后一个星期二的4:30执行
字母W
表示离给定日期最近的工作日(周一到周五),W 字符代表着平日 (Mon-Fri),并且仅能用于日域中。
如:(0 30 2 15W * ?),如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第16 天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。
字母C
指和calendar联系后计算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天。
不常用,可以不了解