Quartz官网
http://www.quartz-scheduler.org/
特点
主要用到的设计模式
三个核心概念
Quartz 体系结构
JobDetail
scheduler
trigger
-SimpleTrigger
-CronTrigger
重要组成
Job
JobDetail
JobBuilder
JobStore
Trigger
TriggerBuilder
ThreadPool
Scheduler
Calendar
监听器
JobListener
TriggerListener
SchedulerListener
依赖
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>2.3.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-simpleartifactId>
<version>1.7.25version>
<scope>compilescope>
dependency>
定义任务 MyJob.java
package timer;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateFormat.format(new Date()));
}
}
调度任务 QuartzDemo.java
package timer;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzDemo {
public static void main(String[] args) throws SchedulerException {
// 创建JobDetail
JobDetail jobDetail = JobBuilder
.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
// 每2s执行一次,无限循环
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.repeatForever();
// 创建Trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(scheduleBuilder)
.build();
// 通过工厂方法创建Scheduler实例
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail, trigger);
}
}
1、Job 源码:
package org.quartz;
public interface Job {
void execute(JobExecutionContext context)
throws JobExecutionException;
}
2、Job 的生命周期:
每次调度器执行 Job 时,调用 execute 方法前会创建一个新的 Job 实例
调用完成后,关联的 Job 对象实例会被释放,释放的实例会被垃圾回收机制回收
3、JobDetail:
JobDetail 为 Job 实例提供了许多设置属性,以及 JobDataMap 成员变量属性,
它用来存储特定 Job 实例的状态信息,调度器需要借助 JobDetail 对象来添加 Job 实例
4、JobDetail 重要属性
name
group 默认值DEFAULT
jobClass
jobDataMap
// 创建JobDetail
JobDetail jobDetail = JobBuilder
.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
// 打印jobDetail属性
System.out.println(jobDetail.getKey().getName()); // myJob
System.out.println(jobDetail.getKey().getGroup()); // group1
System.out.println(jobDetail.getJobClass().getName()); // timer.MyJob
1、JobExecutionContext:
Scheduler 给 Job 传递参数
2、JobDataMap:
可以装载任何可序列化的数据对象
实现了 Map 接口
设置 JobDataMap 部分代码
// 创建JobDetail
JobDetail jobDetail = JobBuilder
.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.usingJobData("name", "jobDetail")
.build();
// 每2s执行一次,无限循环
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.repeatForever();
// 创建Trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.usingJobData("name", "trigger")
.withSchedule(scheduleBuilder)
.build();
获取 JobDataMap
方法一:直接从 JobDataMap 对象中获取
package timer;
import org.quartz.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 获取 jobkey
JobKey jobKey = jobExecutionContext.getJobDetail().getKey();
System.out.println(jobKey.getName()); // myJob
System.out.println(jobKey.getGroup()); // group1
// 获取JobDetail的DataMap
JobDataMap jobDetailDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
System.out.println(jobDetailDataMap.getString("name"));
// jobDetail
// 获取Trigger的DataMap
JobDataMap triggerDataMap = jobExecutionContext.getTrigger().getJobDataMap();
System.out.println(triggerDataMap.getString("name"));
// trigger
// 获取合并后的DataMap
JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap();
System.out.println(dataMap.getString("name"));
// trigger
}
}
方法二:定义同名变量获取
package timer;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MyJob implements Job {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println(this.name);
}
}
Trigger 是触发器,用来告诉调度程序作业什么时候触发
触发器通用属性
JobKey: Job 实例的标识,触发器被触发时,指定的 job 实例会执行
StartTime:触发器的时间表首次被触发的时间,类型是 Java.util.Date
EndTime:触发器不再被触发的时间 Java.util.Date
设置部分代码
// 获取3秒后的时间
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000);
// 获取6秒后的时间
Date endDate = new Date();
endDate.setTime(endDate.getTime() + 3000);
// 创建Trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(startDate)
.endAt(endDate)
.usingJobData("name", "trigger")
.withSchedule(scheduleBuilder)
.build();
Job 中获取 Trigger 数据
package timer;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Trigger;
import java.text.SimpleDateFormat;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Trigger trigger = jobExecutionContext.getTrigger();
// 获取开始时间和结束时间
System.out.println(dateFormat.format(trigger.getStartTime()));
System.out.println(dateFormat.format(trigger.getEndTime()));
// 获取JobKey
System.out.println(trigger.getJobKey().getName());
System.out.println(trigger.getJobKey().getGroup());
}
}
指定时间段内执行一次作业任务
或者在指定的时间间隔内多次执行作业任务
任务
package timer;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateFormat.format(new Date()));
}
}
示例 1
// 获取3秒后的时间
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000);
// 3秒钟之后执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(startDate)
.build();
示例 2
// 获取3秒后的时间
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000);
// 每2s执行一次,无限循环
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.withRepeatCount(3);
// 3s之后执行第一次,之后每隔2s执行一次,重复3次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(startDate)
.withSchedule(scheduleBuilder)
.build();
示例 3
// 获取3秒后的时间
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000L);
// 获取6秒后的时间
Date endDate = new Date();
endDate.setTime(endDate.getTime() + 6000L);
// 每2s执行一次,无限循环
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.withRepeatCount(3);
// 3s之后执行第一次,之后每隔2s执行一次,6秒之后结束
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(startDate)
.endAt(endDate)
.withSchedule(scheduleBuilder)
.build();
注意:
基于日历的作业调度器,而不是像 SimpleTrigger 那样精确指定时间间隔,较为常用
格式:
秒 分 时 日 月 周 年
特殊符号说明
, 或 10,12
- 区间 10-12
/ 每 */5
* 所有值 *
? 不指定
提示
示例
// 每2秒执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * * * ? *"))
.build();
StdSchedulerFactory
配置参数一般存储在 quartz.properties
主要函数
// 将job和trigger注册到scheduler
Date scheduleJob(JobDetail jobDetail, Trigger trigger)
// 启动
void start()
// 暂停
void standby()
// 关闭
// true 等待所有任务执行完成再关闭
// false 直接关闭
void shutdown()
文档位置和加载顺序
jar 包下有默认配置
组成部分
新建 maven webapp
依赖
webmvc
context
aop
core
配置 Quartz 的两种方式:
项目结构
$ tree -I target
.
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── mouday
│ │ ├── controller
│ │ │ └── IndexController.java
│ │ └── quartz
│ │ ├── ComplexJob.java
│ │ └── SimpleJob.java
│ ├── resources
│ │ └── dispatcher-servlet.xml
│ └── webapp
│ ├── WEB-INF
│ │ └── web.xml
│ └── index.jsp
1、pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>spring-mvc-demoartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<spring.version>5.2.6.RELEASEspring.version>
properties>
<build>
<finalName>springquartzfinalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.2version>
<configuration>
<port>8080port>
<path>/path>
<uriEncoding>UTF-8uriEncoding>
<ignorePackaging>trueignorePackaging>
<contextFile>src/main/webapp/WEB-INF/web.xmlcontextFile>
<contextReloadable>truecontextReloadable>
configuration>
plugin>
plugins>
build>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-expressionartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>2.3.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-simpleartifactId>
<version>1.7.25version>
<scope>compilescope>
dependency>
dependencies>
project>
2、src/main/webapp/index.jsp
<html>
<body>
<h2>Hello World!h2>
body>
html>
3、src/main/webapp/WEB-INF/web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>dispatcherservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:dispatcher-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<welcome-file-list>
<welcome-file>index.jspwelcome-file>
welcome-file-list>
web-app>
4、src/main/resources/dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=utf-8value>
list>
property>
bean>
list>
property>
bean>
<mvc:annotation-driven/>
<context:component-scan base-package="com.mouday"/>
<mvc:view-controller path="/" view-name="index"/>
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
bean>
<bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="simpleJob"/>
<property name="targetMethod" value="sayHello"/>
bean>
<bean id="complexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mouday.quartz.ComplexJob"/>
<property name="jobDataMap">
<map>
<entry key="name" value="Tom"/>
map>
property>
<property name="Durability" value="true"/>
bean>
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="simpleJobDetail"/>
<property name="startDelay" value="1000"/>
<property name="repeatInterval" value="2000"/>
bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="complexJobDetail"/>
<property name="cronExpression" value="0/3 * * * * ? *"/>
bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="simpleJobDetail"/>
<ref bean="complexJobDetail"/>
list>
property>
<property name="triggers">
<list>
<ref bean="simpleTrigger"/>
<ref bean="cronTrigger"/>
list>
property>
bean>
beans>
5、src/main/java/com/mouday/controller/IndexController.java
package com.mouday.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 仅用于SpringMVC服务测试
*/
@Controller
public class IndexController {
@GetMapping("/login")
@ResponseBody
public String login(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "password", required = false) String password
) {
return "name:" + name + " password:" + password;
}
}
6、src/main/java/com/mouday/quartz/SimpleJob.java
package com.mouday.quartz;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component("simpleJob")
public class SimpleJob {
public void sayHello(){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("SimpleJob "+ dateFormat.format(new Date()) );
}
}
7、src/main/java/com/mouday/quartz/ComplexJob.java
package com.mouday.quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ComplexJob extends QuartzJobBean {
private String name;
public void setName(String name) {
this.name = name;
}
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("ComplexJob name: " + this.name + " " + dateFormat.format(new Date()));
}
}