文章目录
quartz简介
定时任务处理,quartz及Spring整合quartz去快速解决企业开发中的任务调度问题。
quartz是开源且具有丰富特性的“任务调度库”,能够集成于任何的Java应用,任务job被定义为标准的Java组件,能够执行任何你想要实现的功能。quartz调度包含许多企业级的特性,如JTA事务、集群的支持。
简言之,quartz就是基于Java实现的任务调度框架,用于执行任何你想要执行的任务。
quartz应用案例
第一步:导入jar包;
第二步:获取一个实例;
第三步:创建一个任务;
第四步:任务加载到对象当中;
quartz的设计模式
- Builder模式
- Factory模式
- 组件模式
- 链式编程
quartz的核心概念
- 任务Job:Job就是你想要实现的任务类,每一个Job必须实现org.quartz.Job接口,只需实现接口定义的execute()方法;
- 触发器Trigger:Trigger是执行任务的触发器,比如每天定时三点发一份统计邮件,Trigger将会设置3点执行该任务。Trigger主要包含SimpleTrigger和CronTrigger两种;
- 调度器Scheduler:任务的调度器,它会将任务和触发器整合起来,负责基于Trigger设定的时间来执行Job;
quartz的api讲解
-
Scheduler用于与调度程序交互的主程序接口,Scheduler调度程序-任务执行计划表,只有安排进执行计划的任务Job(通过scheduler.schedulerJob()方法安排进执行计划),当它预先定义的执行时间到了的时候(任务触发trigger触发器),该任务才会执行;
-
Job我们预先定义的希望在未来时间能被调度程序执行的任务类,可以自定义;
-
JobDetail:使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建的;
-
JobBuilder:用于声明一个任务实例,也可以定义关于该任务的详情如任务名、组名等,这个声明的实例将会作为实际执行的认为;
-
JobDataMap:可以包含不限量的(序列化的)数据对象,在Job实例执行的时候,可以使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法;
-
Trigger:触发器,Trigger对象是用来触发执行Job的。当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候会执行。定义了一个已经被安排的任务将会在什么时候执行的时间条件,比如每2秒就执行一次;
-
TriggerBuilder:触发器创建器,用于创建触发器trigger实例;
-
JobListener、TriggerListener、SchedulerListener监听器,用于对组件的监听。
quartz的使用
(1)导包、创建HelloJob任务类
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 不引入quartz-jobs也可以 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.1</version>
</dependency>
public class HelloJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
//输出当前时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = dateFormat.format(date);
System.out.println("正在执行数据库备份工作,时间为:"+ dateString);
}
}
第二步:创建任务调度类(触发器、调度器)
public class HelloSchedulerDemo {
public static void main(String[] args) throws Exception {
//1.调度器(Scheduler),从工厂中获取调度的实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//2. 任务实例(JobDetail)
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)//加载任务类,与HelloJob实现绑定,HelloJob得实现Job接口
.withIdentity("job1", "group1")//任务的名称(唯一实例)
.build();
//3. 触发器(Trigger)
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()//马上启动
.withIdentity("trigger1", "group1")//触发器的名称(唯一标识)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5))//每5秒重复执行
.build();
//让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
scheduler.scheduleJob(jobDetail,trigger);
//启动
scheduler.start();
}
}
Spring整合quartz
- 导入相关依赖
<!-- 定时任务 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.1</version>
</dependency>
- 编写任务类,该类需要继承QuartzJobBean 。
package com.xingze.job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class FirstJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("定时任务1开始执行......");
}
}
- 在spring配置文件中配置作业类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">
<bean name="firstJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.xingze.job.FirstJob"/>
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="0"/>
</map>
</property>
</bean>
<!-- 按照一定频率的触发器 -->
<!-- <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">-->
<!-- <property name="jobDetail" ref="firstJob"/>-->
<!-- <property name="startDelay" value="0"/>-->
<!-- <property name="repeatInterval" value="2000"/>-->
<!-- </bean>-->
<!-- Cron表达式触发器 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="firstJob"/>
<property name="cronExpression" value="0/5 * * * * ?"/>
</bean>
<!-- 配置调度工厂-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!-- <ref bean="simpleTrigger"/>-->
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
</beans>
org.springframework.scheduling.quartz.JobDetailBean有两个属性.
- jobClass属性即我们在java代码中定义的任务类.
- jobDataAsMap属性即该任务类中需要注入的属性值.
Quartz的作业触发器有两种(两种任选其一就行)
- org.springframework.scheduling.quartz.SimpleTriggerFactoryBean:只支持按照一定频度调用任务,如每隔30分钟运行一次.
- org.springframework.scheduling.quartz.CronTriggerFactoryBean:支持到指定时间运行一次,如每天12:00运行一次等.
CORN表达式
# 周六、周日每5分钟执行一次
0 0/5 * ? * SAT,SUN
# 每天 每5分钟执行一次
0 0/5 23-10 ? * *
Job和JobDetail
- Job:工作任务调度的接口,任务类需要实现该接口。该接口中定义execute()方法,类似JDK提供的TimeTask类的run()方法。在里面编写任务执行的业务逻辑;
- Job实例在quartz中的生命周期:每次调度器执行Job时,它在调用execute()方法前会创建一个新的Job实例,当调用完成后,关联的Job对象实例会被释放,释放的实例会被垃圾回收机制回收(每次调用都会生成一个新的Job实例);
- JobDetail:JobDetail为Job实例提供了很多设置属性,以及JobDataMap成员变量属性,它用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例;
- JobDetail 重要属性:name、group、jobClass、jobDataMap
JobExecutionContext介绍
- 当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法;
- Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据;
有状态的Job和无状态的Job
有状态的Job可以理解为多次Job调用期间可以持有一些状态信息,这些状态信息存储在JobDataMap中,而默认的无状态Job每次调用时都会创建一个新的JobDataMap。