quartz
@
Quartz
Quartz简介
强大的开源任务调度框架,纯java实现,精细控制排程
特点
强大的调度功能
灵活的应用方式
分布式和集群能力
主要用到的设计模式
Builder模式 Factory模式 组件模式 链式写法
三个核心概念
调度器 任务 触发器
重要组成
Job JobBuilder JobDetail JobStore
Trigger TriggerBuilder ThreadPool Scheduler
Calendar 一个Trigger可以和多个Calendar关联,以排除或包含某些时间点
监听器 JobListener,TriggerListener,SchedulerListener
第一个quartz程序
Job类
package com.xc.quartz.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
System.out.println("Current Exec Time Is:" + sdf.format(new Date()));
System.out.println("hello");
}
}
Scheduler类
package com.xc.quartz.scheduler;
import com.xc.quartz.job.HelloJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {
//创建JobDetail实例,将该实例与HelloJob Class绑定
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("helloJob", "group1").build();
//创建Trigger
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever();
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger().withIdentity("helloTrigger", "group1").startNow()
.withSchedule(simpleScheduleBuilder).build();
//创建Scheduler实例
StdSchedulerFactory std = new StdSchedulerFactory();
Scheduler scheduler = std.getScheduler();
scheduler.start();
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
System.out.println("Current Exec Time Is:" + sdf.format(new Date()));
scheduler.scheduleJob(jobDetail, simpleTrigger);
}
}
Job&JobDetail
Job
Job接口非常容易实现,只有一个execute方法,再里面编写业务逻辑.
Job实例在Quartz中的生命周期
每次调度器执行job时,它在调用execute方法前会创建一个新的job实例.
当调用完成后,关联的job对象实例会被释放,释放的实例会被垃圾回收机制回收.
JobDetail
JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例.
重要属性
name group JobClass
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("helloJob", "group1").build();
System.out.println("jobDetail.getKey().getName():" + jobDetail.getKey().getName());
System.out.println("jobDetail.getKey().getGroup():" + jobDetail.getKey().getGroup());
System.out.println("jobDetail.getJobClass().getName():" + jobDetail.getJobClass().getName());
JobExecutionContext
当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法;
Job能够通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据.
JobDataMap
在进行任务调度时JobDataMap存储在JobExecutionContext中,非常方便获取.
JobDataMap可以用来装载任何可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它.
JobDataMap实现了JKD的Map接口,并且添加了一些非常方便的方法用来存取基本数据类型.
获取JobDataMap的两种方式:
从Map中直接获取
//创建JobDetail实例,将该实例与HelloJob Class绑定
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("helloJob", "group1")
.usingJobData("message", "helloJobMessage")
.usingJobData("floatJobValue", 3.14F).build();
//创建Trigger
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever();
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger().withIdentity("helloTrigger", "group1")
.usingJobData("message", "helloTriggerMessage")
.usingJobData("doubleTriggerValue", 2.0D)
.startNow().withSchedule(simpleScheduleBuilder).build();
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobKey jobKey = jobDetail.getKey();
System.out.println("JobDetail name and group:" + jobKey.getName() + "-" + jobKey.getGroup());
JobDataMap jobDataMap = jobDetail.getJobDataMap();
System.out.println("jobDataMap-value:" + jobDataMap.getString("message") + "-" + jobDataMap.getFloat("floatJobValue"));
Trigger trigger = jobExecutionContext.getTrigger();
TriggerKey triggerKey = trigger.getKey();
System.out.println("Trigger name and group:" + triggerKey.getName() + "-" + triggerKey.getGroup());
JobDataMap jobDataMap1 = trigger.getJobDataMap();
System.out.println("jobDataMap1-value:" + jobDataMap1.getString("message") + "-" + jobDataMap1.getDouble("doubleTriggerValue"));
JobDataMap mergedJobDataMap = jobExecutionContext.getMergedJobDataMap();
System.out.println("mergedJobDataMap-value:" + mergedJobDataMap.getString("message") + "-" + mergedJobDataMap.getFloat("floatJobValue")
+ "-" + mergedJobDataMap.getDouble("doubleTriggerValue"));
Job实现类中添加setter方法
Job实现类中添加setter方法对应JobDataMap的键值(Quartz框架默认的JobFactory实现类在初始化job实例对象时会自动的调用这些setter方法)
package com.xc.quartz.job;
import org.quartz.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloJob implements Job {
private String message;
private Float floatJobValue;
private Double doubleTriggerValue;
public void setMessage(String message) {
this.message = message;
}
public void setFloatJobValue(Float floatJobValue) {
this.floatJobValue = floatJobValue;
}
public void setDoubleTriggerValue(Double doubleTriggerValue) {
this.doubleTriggerValue = doubleTriggerValue;
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
System.out.println("Current Exec Time Is:" + sdf.format(new Date()));
System.out.println("---hello---");
System.out.println("setter-value:" + message + "-" + floatJobValue
+ "-" + doubleTriggerValue);
}
}
Trigger
Quartz中的触发器用来告诉调用程序作业什么时候触发.
即Trigger对象是用来触发执行Job的.
触发器通用属性:
JobKey
表示job实例的标识,触发器被触发时,该指定的job实例会被执行.
StartTime
表示触发器的时间表首次被触发的时间.
EndTime
指定触发器的不再被触发的时间.
Date now = new Date();
Date endTime = new Date(now.getTime() + 15000);
Date startTime = new Date(now.getTime() + 3000);
//创建Trigger
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever();
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger().withIdentity("helloTrigger", "group1")
.startAt(startTime).endAt(endTime).withSchedule(simpleScheduleBuilder).build();
Trigger trigger = jobExecutionContext.getTrigger();
System.out.println("trigger-attr:" + trigger.getStartTime() + trigger.getEndTime());
SimpleTrigger
SimpleTrigger的作用:
在一个指定时间段内执行一次作业任务
或是在指定的时间间隔内多次执行作业任务
Date now = new Date();
Date endTime = new Date(now.getTime() + 15000);//15秒后停止
Date startTime = new Date(now.getTime() + 3000);//3秒后执行
//创建Trigger
//SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever();//间隔10秒钟执行1次,一直执行
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(3);//间隔2秒钟执行1次,执行3次
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger().withIdentity("helloTrigger", "group1")
.startAt(startTime).endAt(endTime).withSchedule(simpleScheduleBuilder).build();
需要注意的点:
重复次数可以为0,正整数或是SimpleTrigger.REPEAT_INDEFINITELY常量值.
重复执行间隔必须为0或长整数.
一旦被指定了endTime参数,那么它会覆盖重复次数参数的效果.
CornTrigger
CornTrigger的作用:
基于日历的作业调度器,而不是像SimpleTrigger那样精确指定间隔时间,比SimpleTrigger更常用.
Cron表达式
用于配置CornTrigger实例.
是由7个子表达式组成的字符串,描述了时间表的详细信息.
格式:[秒][分][小时][日][月][周][年]
Scheduler
Scheduler-工厂模式
所有的Scheduler实例应该由SchedulerFactory来创建
StdSchedulerFactory
使用一组参数(Java.util.Properties)来创建和初始化Quartz调度器
配置参数一般存储在quartz.properties中
调用getScheduler方法就能创建和初始化调度器对象
Scheduler的主要函数
- Date scheduleJob(JobDetail jobDetail, Trigger trigger)
- void start()
- void standby()
- void shutdown()
quartz.properties
组成部分:
调度器属性
线程池属性
作业存储设置
插件配置
Spring集成Quartz
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
spring-mvc-servlet.xml中添加
<!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,通过targetMethod指定调用方法-->
<bean id="taskJob" class="com.xc.quartz.job.HelloJob2"/>
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="group" value="job_work"/>
<property name="name" value="job_work_name"/>
<!--false表示等上一个任务执行完后再开启新的任务-->
<property name="concurrent" value="false"/>
<property name="targetObject">
<ref bean="taskJob"/>
</property>
<property name="targetMethod">
<value>execute</value>
</property>
</bean>
<!-- 调度触发器 -->
<bean id="myTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="work_default_name"/>
<property name="group" value="work_default"/>
<property name="jobDetail">
<ref bean="jobDetail"/>
</property>
<property name="cronExpression">
<value>* * * * * ? *</value>
</property>
</bean>
<!-- 调度工厂 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="myTrigger"/>
</list>
</property>
</bean>
package com.xc.quartz.job;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloJob2 {
public void execute() throws JobExecutionException {
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
System.out.println("Current Exec Time Is:" + sdf.format(new Date()));
System.out.println("---hello---");
}
}