Quartz入门
文章目录
Quartz—学习01—Quartz入门
Quartz—学习02—Quartz源码阅读
一、Quartz的介绍
1-1、什么是Quartz
Quartz是一个由java编写的开源作业调度框架。
1-2、Quartz的基本概念
- Job:Job接口只用一个execute方法,Job表示每一次任务需要做的具体工作。
- JobDetail:用于定义作业的实例。JobDetailImpl对象中有一个jobClass对象,用于保存Job信息的。
- Trigger:定义执行给定作业的计划的组件。比如每天三点执行,每个月1号执行…
- Scheduler:与调度程序交互的主要API。Scheduler的生命周期是从其创建以后一直到调用shutdown方法为止,当你使用SchedulerFactory创建对应的Scheduler实例对象,如果没有调用shutdown方法,Scheduler将不会终止。
1-3、Quartz企业级有哪些应用
现在在一家金融机构上班,我们有应用的地方:每天、每月都会生成对账文件给到其他金融机构和银行;有些因为网络问题没有通知给商户、客户的通知,会没5分钟在把通知失败的通知在进行通知操作。
二、Quartz简单的Demo
2-1、简单实例
项目的目录结构
下面是demo的pom.xml文件,引入quartz的jar包。
<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.0</modelVersion>
<groupId>com.liu.quartz</groupId>
<artifactId>quartz-learn-001</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
自定义Job
package com.liu.quart.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* @desc 自定义Job,实现Quartz的Job接口,
* 重写execute方法。
*/
public class CustomJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("----自定义Job--的execute方法!!");
}
}
自定义Trigger监听器
package com.liu.quart.listener;
import org.quartz.JobExecutionContext;
import org.quartz.Trigger;
import org.quartz.Trigger.CompletedExecutionInstruction;
import org.quartz.TriggerListener;
/**
* @desc 自定有Trigger监听器,实现TriggerListener
*/
public class CustomTriggerListener implements TriggerListener{
public String getName() {
return "CustomTrigger";
}
public void triggerFired(Trigger trigger, JobExecutionContext context) {
System.out.println("###################");
System.out.println("自定义触发器----触发操作");
}
/**
* Trigger触发后,Job要执行时由Scheduler调用这个方法,如果vetoJobExecution放回是true,
* 则对应的Job将不会被执行。
*/
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
return false;
}
public void triggerMisfired(Trigger trigger) {
System.out.println("自定义触发器----未触发操作");
}
/**
* Trigger触发后,Job被执行以后,Scheduler在调用这个方法
*/
public void triggerComplete(Trigger trigger, JobExecutionContext context, CompletedExecutionInstruction triggerInstructionCode) {
System.out.println("自定义触发器----Job完成后的操作");
}
}
测试类
package com.liu.quart;
import java.util.Date;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import com.liu.quart.job.CustomJob;
import com.liu.quart.listener.CustomTriggerListener;
/**
* @desc Test类
*/
public class Test {
public static void main(String[] args) {
// 01-定义JobDetail
JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setName("jobDetail_name");
jobDetail.setGroup("Job_Group");
jobDetail.setJobClass(CustomJob.class);
// 02-设置触发器
SimpleTriggerImpl trigger = new SimpleTriggerImpl();
trigger.setName("Trigger_Name");
trigger.setFireInstanceId("Fire_Instance");
trigger.setStartTime(new Date());
trigger.setRepeatCount(3); // 重复次数
trigger.setRepeatInterval(10000L); // 重复间隔(ms)
// 03-创建触发器,并启动
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = null;
try {
scheduler = schedulerFactory.getScheduler();
scheduler.getListenerManager().addTriggerListener(new CustomTriggerListener());
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
2-2、与Spring整合的简单实例
创建一个maven的web工程,工程结构如下图
pom.xml文件引入响应的文件
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<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>
</dependencies>
自动以Job
/**
* @desc 自定义Job
*/
public class CustomJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("自定义job----执行内容");
}
}
application.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!-- 开启注解配置 -->
<context:annotation-config />
<!-- 扫描包的范围 -->
<context:component-scan base-package="com.liu"></context:component-scan>
</beans>
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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!-- 1.JobDetail设置 -->
<bean name="customJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 指定job的名称 -->
<property name="name" value="job_name" />
<!-- 指定job的分组 -->
<property name="group" value="job__group" />
<!-- 指定具体的job类 -->
<property name="jobClass" value="com.liu.spring.quartz.job.CustomJob" />
<!-- 必须设置为true,如果为false,当没有活动的触发器与之关联时会在调度器中会删除该任务 -->
<property name="durability" value="true" />
<!-- 指定spring容器的key,如果不设定在job中的jobmap中是获取不到spring容器的 -->
<property name="applicationContextJobDataKey" value="applicationContext" />
</bean>
<!-- 2.触发器设置 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 指定Trigger的名称 -->
<property name="name" value="trigger_name" />
<!-- 指定Trigger的名称 -->
<property name="group" value="trigger_group" />
<!-- 指定Tirgger绑定的Job -->
<property name="jobDetail" ref="customJobDetail" />
<!-- 指定Cron 的表达式 ,当前是每隔10s运行一次 -->
<property name="cronExpression" value="0/10 * * * * ?" />
</bean>
<!-- 3.定义调度器,并将Trigger注册到调度器中 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
</beans>
web.xml内容,注意一点:不要把application.xml和spring-quartz.xml写在一起,contextConfigLocation加载的文件和springmvc加载的文件不要是一个,否则就会初始化两次,造成每次job都被运行了两次。
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置欢迎页面 -->
<welcome-file-list>
<welcome-file>/WEB-INF/context/index.jsp</welcome-file>
</welcome-file-list>
<!-- 最先加载的,加载其他配置文件,注意其路径问题! -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:spring/spring-*.xml
</param-value>
</context-param>
<!-- listener第二加载 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- filter第三加载,配置编码格式的 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--最后加载的 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
三、Cron表达式
3-1、corn表达式介绍
Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式如下表,注意中文解释中用“-”是为了好看,实际域与域之间是用空格隔开的。
表达式 | 中文解释 |
---|---|
Seconds Minutes Hours DayofMonth Month DayofWeek Year | 秒-分-时-日期-月-星期-年 |
Seconds Minutes Hours DayofMonth Month DayofWeek | 秒-分-时-日期-月-星期 |
各个域能填的值的范围
域名 | 取值范围 | 可用的特殊值 |
---|---|---|
秒(Seconds) | 0~59的整数 | , - * / |
分(Minutes) | 0~59的整数 | , - * / |
小时(Hours) | 0~23的整数 | , - * / |
日期(DayofMonth) | 1~31的整数(但是你需要考虑你月的天数) | ,- * ? / L W C |
月份(Month) | 1~12的整数或者 JAN-DEC | , - * / |
星期(DayofWeek) | 1~7的整数或者 SUN-SAT (1=SUN) | ** , - * ? / L C #** |
年(可选,留空)(Year) | 1970~2099 | , - * / |
特殊符号的说明:
- *:表示匹配该域的任意值。
- ?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。
- -:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次 。
- /:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.
- ,:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。
- L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。
- W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。
- LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
- #:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。
3-2、常用corn表达式
(1)** 0 0 2 1 * ? * ** 表示在每月的1日的凌晨2点调整任务
(2)0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
(3)0 15 10 ? 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作
(4)0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
(5)0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
(6)0 0 12 ? * WED 表示每个星期三中午12点
(7)** 0 0 12 * * ? ** 每天中午12点触发
(8)**0 15 10 ? * *** 每天上午10:15触发
(9)0 15 10 * * ? 每天上午10:15触发
(10)**0 15 10 * * ? * ** 每天上午10:15触发
(11)0 15 10 * * ? 2005 2005年的每天上午10:15触发
(12)0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
(13)0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
(14)0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
(15)0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
(16)0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
(17)0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
(18)0 15 10 15 * ? 每月15日上午10:15触发
(19)0 15 10 L * ? 每月最后一日的上午10:15触发
(20)0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
(21)0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
(22)0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
本文参考 :
[1]: https://www.cnblogs.com/javahr/p/8318728.html