1 Quartz介绍

  • 定时任务,无论是互联网公司还是传统的软件行业都是必不可少的,Quartz是好多优秀的定时任务开源框架的基础的。
  • 我们应用最简单和最基础的配置,不需要太多参数,就可以轻松掌握企业中的定时任务处理。

2 Quartz概念

  • Quartz是OpenSymphony开源组织在Job Scheduling领域又一个开源项目,它可以在J2EE和J2SE应用程序相结合,也可以单独使用。
  • Quartz是开源且具有丰富特性的“任务调度库”,能够集成于任何的Java应用,小到独立的应用,大到电子商业系统。
  • Quartz能够创建亦简单亦复杂的调度,以执行上十、上百,甚至上万的任务。
  • 任务Job被定义为标准的Java组件,能够执行任何你想要的功能。
  • Quartz调度框架包含许多企业级的特性,如JTA事务、集群的支持。
  • 简而言之,Quartz就是基于Java实现的任务调度框架,用于执行你想要执行的任何任务。

3 Quartz的运行环境

  • Quartz可以运行嵌入在另一个独立式应用程序。
  • Quartz可以在应用程序服务器(或者Servlet容器)内被实例化,并且参与事务。
  • Quartz可以作为一个独立的程序运行(其自己的Java虚拟机内),可以通过RMI使用。
  • Quartz可以被实例化,作为独立的项目集群(负载均衡和故障转移的功能),用于作业的执行。

4 Quartz的核心概念

4.1 任务 Job

  • Job就是你想要实现的任务类,每一个Job必须实现org.quartz.Job接口,且只需要实现接口定义的execute()方法。

4.2 JobDetail

  • 表示一个具体的可执行的调度程序,Job是这个可执行调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。

4.3 触发器 Trigger

  • Trigger就是执行任务的触发器,比如每天定时3点发送一份统计邮件,Trigger将会设置3点进行该任务。
  • Trigger主要包含SimpleTrigger和CronTrigger两种。

4.4 调度器 Scheduler

  • Scheduler为任务的调度器,它会将任务Job和触发器Trigger整合起来,负责基于Trigger设定的时间来执行Job。

5 Quartz的体系结构

6 Quartz常用的API

6.1 Scheduler

  • Scheduler--和调度程序交互的主要API。

6.2 Job

  • Job就是你想要实现的任务类,每一个Job必须实现org.quartz.Job接口,且只需要实现接口定义的execute()方法。

6.3 JobDetail

  • 表示一个具体的可执行的调度程序,Job是这个可执行调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。

6.4 Trigger

  • 触发器,定义执行给定作业的计划的组件。

6.5 JobBuilder

  • 用于定义/构建JobDetail实例。

6.6 TriggerBuilder

  • 用于定义/构建Trigger实例。

7 Quartz的入门

7.1 导入环境所需要的jar包的maven坐标

<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<!-- quartz-jobs -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.2</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

7.2 在classpath类路径下新建log4j.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="default" class="org.apache.log4j.ConsoleAppender">
<param name="target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p] %d{dd MMM hh:mm:ss.SSS aa} %t [%c]%n%m%n%n"/>
</layout>
</appender> <logger name="com.how2java">
<level value="error" />
</logger> <root>
<level value="error" />
<appender-ref ref="default" />
</root> </log4j:configuration>

7.3 入门示例

  • 示例:
  • MailJob.java
package com.sunxiaping;

import org.quartz.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; public class MailJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
Object email = jobDataMap.get("email"); System.out.println("邮件发送给" + email + ",发送时间是:" + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
}
}
  • QuartzTest.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
/**
* ①创建JobDetail实例,通过JobBuilder来创建
*
*/
JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
.usingJobData("email", "123456789@qq.com")
.build();
/**
* ②创建Trigger示例,通过TriggerBuilder来创建。
* 在Quartz中,Job只是用来表示 什么任务,而Trigger用来表示 什么时候做,怎么做(设置执行的条件等)?
*/
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow() //立即开始,在Scheduler调度器开启之后
//设置调度的参数 withIntervalInSeconds(2) 表示时间间隔是2秒,repeatForever() 一直重复执行,直到天崩地裂,海枯石烂。
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build(); //通过StdSchedulerFactory工厂的getDefaultScheduler()方法获取Scheduler调取器实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); /**
*③ 调度器将jobDetail和trigger关联起来
*/
scheduler.scheduleJob(jobDetail, trigger); /**
* ④ 触发器开启
* 注意:
* scheduler被停止后,除非重新实例化,否则不能重新启动;
* 只有当scheduler启动后,即使处于暂停状态也不行,trigger才会被触发(job才会被执行)
*/
scheduler.start();
} }

8 Job和JobDetail介绍

8.1 Job

  • Job:工作任务调度的接口,任务类需要实现该接口。该接口中定义execute方法,类似于JDK提供的TimeTask类的run方法。在里面编写任务执行的业务逻辑即可。
  • Job实例在Quartz中的生命周期:每次调度器执行Job的时候,它会在调用execute方法前创建一个新的Job实例,当调用完成之后,关联的Job对象实例会被释放,释放的实例会被垃圾回收器回收。

8.2 JobDetail

  • JobDetail:JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存储特定的Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。
  • JobDetail重要属性:name、group、jobClass、jobDataMap。

8.3 应用示例

  • 示例:
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
/**
* ①创建JobDetail实例,通过JobBuilder来创建
*
*/
JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
.usingJobData("email", "123456789@qq.com")
.build(); System.out.println("名称:" + jobDetail.getKey().getName());
System.out.println("组的名称:" + jobDetail.getKey().getGroup()); //如果没有指定,默认以DEFAULT为组名
System.out.println("任务类:" + jobDetail.getJobClass().getName()); /**
* ②创建Trigger示例,通过TriggerBuilder来创建。
* 在Quartz中,Job只是用来表示 什么任务,而Trigger用来表示 什么时候做,怎么做(设置执行的条件等)?
*/
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow() //立即开始,在Scheduler调度器开启之后
//设置调度的参数 withIntervalInSeconds(2) 表示时间间隔是2秒,repeatForever() 一直重复执行,直到天崩地裂,海枯石烂。
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build(); //通过StdSchedulerFactory工厂的getDefaultScheduler()方法获取Scheduler调取器实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); /**
*③ 调度器将jobDetail和trigger关联起来
*/
scheduler.scheduleJob(jobDetail, trigger); /**
* ④ 触发器开启
* 注意:
* scheduler被停止后,除非重新实例化,否则不能重新启动;
* 只有当scheduler启动后,即使处于暂停状态也不行,trigger才会被触发(job才会被执行)
*/
scheduler.start();
} }

9 JobExecutionContext和JobDataMap介绍

9.1 JobExecutionContext

  • 当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法。
  • Job能够通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。
  • 示例:
package com.sunxiaping;

import org.quartz.*;

import java.util.Date;

public class MailJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
//获取JobDetail
JobDetail jobDetail = context.getJobDetail();
System.out.println("工作任务的名称:" + jobDetail.getKey().getName() + ",工作任务的组:" + jobDetail.getKey().getGroup());
System.out.println("任务类的名称(全类名):"+jobDetail.getJobClass().getName());
System.out.println("任务类的名称:"+jobDetail.getJobClass().getSimpleName());
//获取Trigger
Trigger trigger = context.getTrigger(); System.out.println("触发器的名称:" + trigger.getKey().getName() + ",触发器的组:" + trigger.getKey().getGroup()); Date fireTime = context.getFireTime();
System.out.println("当前任务的执行时间:"+fireTime);
Date nextFireTime = context.getNextFireTime();
System.out.println("下一次任务的执行时间:"+nextFireTime);
}
}

9.2 JobDataMap

9.2.1 使用Map获取

  • 在进行任务调度的时候,JobDataMap存储在JobExecutionContext中,非常方便虎丘。
  • JobDataMap可以用来装载任何可序列化的数据对象,当Job实例对象被执行的时候这些参数对象会传递给它。
  • JobDataMap实现了JDK的Map接口,并且添加了非常方便的方法用来存取基本数据类型。
  • 示例:
  • MailJob.java
package com.sunxiaping;

import org.quartz.*;

public class MailJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
String message = context.getJobDetail().getJobDataMap().getString("message");
System.out.println("JobDetail-->JobDataMap:"+message); message = context.getTrigger().getJobDataMap().getString("message");
System.out.println("Trigger-->JobDataMap:"+message);
}
}
  • QuartzTest.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
//usingJobData 非常方便的存取基本类型数据
.usingJobData("message", "JobDetail")
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow() //立即开始,在Scheduler调度器开启之后
//设置调度的参数 withIntervalInSeconds(2) 表示时间间隔是2秒,repeatForever() 一直重复执行,直到天崩地裂,海枯石烂。
.usingJobData("message","trigger")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start();
} }

9.2.2 Job实现类中添加Setter方法对应JobDataMap的键值

  • Quartz框架默认的JobFactory实现类在初始化Job实例对象的时候回自动的调用这些Setter方法。
  • 示例:
package com.sunxiaping;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; public class MailJob implements Job { private String message; public void setMessage(String message) {
this.message = message;
} public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println(message);
}
}
  • 注意:这种方式有弊端,那就是如果遇到同名的key,Trigger中的JobDataMap会覆盖掉JobDetail中的JobDataMap中的值。

10 有状态的Job和无状态的Job

  • 其实就是@PersistJobDataAfterExecution注解的使用。
  • 有状态的Job可以理解为多次Job调用期间可以持有一些状态信息,这些状态信息存储在JobDataMap中。
  • 默认情况下,无状态的Job每次调用都会创建一个新的JobDataMap。
  • 示例:
  • MailJob.java
package com.sunxiaping;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution; @PersistJobDataAfterExecution
public class MailJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException {
int count = context.getJobDetail().getJobDataMap().getInt("count");
count++;
System.out.println(count);
context.getJobDetail().getJobDataMap().put("count", count); }
}
  • QuartzTest.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
//usingJobData 非常方便的存取基本类型数据
.usingJobData("count", 0)
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow() //立即开始,在Scheduler调度器开启之后
//设置调度的参数 withIntervalInSeconds(2) 表示时间间隔是2秒,repeatForever() 一直重复执行,直到天崩地裂,海枯石烂。
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start();
} }

11 Trigger介绍

  • Quartz有一些不同的触发器类型,不过,用的最多的还是SimpleTrigger和CronTrigger。
  • JobKey:表示Job实例的标识,触发器被触发时,该指定的Job实例会被执行。
  • startTime:表示触发器第一次开始被触发的时间,它的数据类型是java.util.Date。
  • endTime:表示触发器终止被触发的时间,它的数据类型是java.util.Date。
  • 示例:
  • MailJob.java
package com.sunxiaping;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey; import java.util.Date; public class MailJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException {
//表示Job实例的标识,触发器被触发时,该指定的Job实例会被执行
JobKey jobKey = context.getTrigger().getJobKey();
System.out.println("JobKey的名称:" + jobKey.getName() + ",JobKey组的名称:" + jobKey.getGroup());
//触发器第一次开始被触发的时间
Date startTime = context.getTrigger().getStartTime();
System.out.println("startTime:" + startTime);
//触发器终止被触发的时间
Date endTime = context.getTrigger().getEndTime();
System.out.println("endTime:" + endTime); System.out.println("当前时间是:"+new Date()); }
}
  • QuartzTest.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000); Date endDate = new Date();
endDate.setTime(endDate.getTime() + 10000); JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
//usingJobData 非常方便的存取基本类型数据
.usingJobData("count", 0)
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
// .startNow() //立即开始,在Scheduler调度器开启之后
.startAt(startDate)//设置任务的开始时间
.endAt(endDate) //设置任务的结束时间 //设置调度的参数 withIntervalInSeconds(2) 表示时间间隔是2秒,repeatForever() 一直重复执行,直到天崩地裂,海枯石烂。
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }

12 SimpleTrigger触发器

  • SimpleTrigger对于设置和使用时最为简单的一种QuartzTrigger。
  • 它是为那种需要在特定的日期/时间启动,且以一种可能的间隔时间重复执行n次的Job所设计的。
  • 示例:在一个指定的时间段内,执行一次作业任务
  • MailJob.java
package com.sunxiaping;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; import java.util.Date; public class MailJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("当前时间是:"+new Date()); }
}
  • QuartzTest.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000); Date endDate = new Date();
endDate.setTime(endDate.getTime() + 10000); JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
// .startNow() //立即开始,在Scheduler调度器开启之后
.startAt(startDate)//设置任务的开始时间
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
  • 示例:在指定的时间间隔内多次执行作业任务
  • MailJob.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000); Date endDate = new Date();
endDate.setTime(endDate.getTime() + 10000); JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
// .startNow() //立即开始,在Scheduler调度器开启之后
.startAt(startDate)//设置任务的开始时间
//设置调度的参数 withIntervalInSeconds(2) 表示时间间隔是2秒,withRepeatCount(4) 执行5次 每1秒执行一次,连续执行5次后停止
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).withRepeatCount(4))
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
  • 示例:设置任务的结束时间
  • MailJob.java
package com.sunxiaping;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; import java.util.Date; public class MailJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("当前时间是:"+new Date()); }
}
  • QuartzTest.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000); Date endDate = new Date();
endDate.setTime(endDate.getTime() + 10000); JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
// .startNow() //立即开始,在Scheduler调度器开启之后
.startAt(startDate)//设置任务的开始时间
.endAt(endDate)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
  • 注意:
  • SimpleTrigger的属性有:开始时间、结束时间、重复次数和重复的时间间隔。
  • 重复次数的属性值可以为0、正整数、或常量SimpleTrigger.REPEAT_INDEFINITELY。
  • 重复的时间间隔属性值必须大于0或长整型的正整数,以毫秒作为时间单位。
  • 如果有指定结束时间属性值,则结束时间属性优先于重复次数属性,这样的好处在于:当我们需要创建一个每间隔10秒就触发一次知道指定的结束时间的Trigger,而无需去计算从开始到结束所重复的次数,我们只需要简单的指定结束书剑和使用REPEAT_INDEFINITELY。

13 CronTrigger触发器

13.1 概述

  • 如果你需要像日历那样按照日程来触发任务,而不是像SimpleTrigger那样每隔特定的间隔时间触发,CronTrigger通常比SimpleTrigger更有用,因为它是基于日历的作业调度。
  • 使用CronTrigger,你可以指定诸如“每个周五中午”,或者“每个工作日的0:30”或者“从每个周一、周三、周五的上午9点到10点之间每隔五分钟”这样的日程来安排触发。甚至,像SimpleTrigger一样,CronTrigger也有一个startTime以指定日程从什么时候开始,也有一个(可选的)endTime以指定何日日程不再继续。

13.2 Cron表达式

  • Cron表达式被用来配置CronTrigger实例。Cron表达式是一个由7个子表达式组成的字符串。每个子表达式都描述了一个单独的日程细节。这些子表达式之间使用空格分隔,分别表示:
  • ①Seconds,秒。
  • ②Minutes,分钟。
  • ③Hours,小时。
  • ④Day-of-Month,月中的天。
  • ⑤Month,月。
  • ⑥Day-of-Week,周中的天。
  • ⑦year(optional field) 年,可选。

  • 单个子表达式可以包含范围或者列表。例如周中的天这个域(‘WED’)可以被替换为''MON-FRI"或"MON,WED,FRI"或者甚至“MON-WED,SAT”。
  • 所有的域中的值都有特定的合法范围,这些值得合法范围相当明显,例如:秒和分钟的合法值是0~59,小时的合法值是0~23,Day-of-Month的合法值是1~31,但是需要注意不同的月份中的天数是不一样的。月份的合法值是1~12(你也可以用字符串JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC来表示)。Days-of-Week可以用1-7来表示(其中1表示星期日)或者用字符串SUN,MON,TUE,WED,THU,FRI,SAT来表示。

  • 示例:
  • 0 0 10,14,16 * * ?:每天上午10点,下午2点,4点。
  • 0 0/30 9-17 * * ? :每天早上9点晚上5点工作,从0分钟开始,每隔30分钟发送一次。
  • 0 0 12 ? * WED :每个星期三中午12点。
  • 0 0 12 * * ?:每天中午12点触发。
  • 0 15 10 ? * * :每天上午10点15分触发。
  • 0 12 10 * * ? 2050:2050年上午10点12分触发。
  • 0 * 14 * * ?:每天下午2点到下午2点59分,每隔1分钟触发一次。
  • 0 0/55 14 * * ?:每天下午2点到下午2点55分钟,从0开始到55分钟触发。
  • 0 0/55 14,18 * * ?:每天下午2点到2:55期间和下午6点到6:55期间,从0开始到55分钟触发。
  • 0 0-5 14 * * ?:每天下午2点到下午2:05期间每隔1分钟触发。
  • 0 10,44 14 ? 3 WED:每年三月的星期三下午2点10和2点44触发。
  • 0 15 10 ? * MON-FRI:周一到周五的上午10点15分触发。
  • 0 15 10 15 * ?:每月15号上午10点15分触发。
  • 0 15 10 L* ?:每月最后一日的上午10点15分触发。
  • 0 15 10 ? * 6L:每月最后一个星期五上午10点15分触发。
  • 0 15 10 ?* 6#3:每月的第三个星期五上午10点15分触发。
  • 示例:
  • MailJob.java
package com.sunxiaping;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /**
* Quartz测试
*/
public class QuartzTest { public static void main(String[] args) throws SchedulerException {
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 3000); Date endDate = new Date();
endDate.setTime(endDate.getTime() + 10000); JobDetail jobDetail = JobBuilder.newJob(MailJob.class)
.withIdentity("job1", "group1")
.build(); Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow() //立即开始,在Scheduler调度器开启之后
.withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ?"))
.build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
  • 提示:
  • L和W可以一起使用。(企业中可用在工资计算,比如每个月5号发工资)
  • #可表示月中的第几个周几。(比如父亲节和母亲节)
  • 周字段英文字母大小写不区分。比如MON==mon。
  • 利用工具,在线生成。

Quartz(一)的更多相关文章

  1. 免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)

    很多的软件项目中都会使用到定时任务.定时轮询数据库同步,定时邮件通知等功能..NET Framework具有“内置”定时器功能,通过System.Timers.Timer类.在使用Timer类需要面对 ...

  2. Quartz

    Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中.它提供了巨大的灵 活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度. eg: ja ...

  3. Spring Quartz实现任务调度

    任务调度 在企业级应用中,经常会制定一些"计划任务",即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发.线程池维 ...

  4. topshelf和quartz内部分享

    阅读目录: 介绍 基础用法 调试及安装 可选配置 多实例支持及相关资料 quartz.net 上月在公司内部的一次分享,现把PPT及部分交流内容整理成博客. 介绍 topshelf是创建windows ...

  5. Quartz.net持久化与集群部署开发详解

    序言 我前边有几篇文章有介绍过quartz的基本使用语法与类库.但是他的执行计划都是被写在本地的xml文件中.无法做集群部署,我让它看起来脆弱不堪,那是我的罪过. 但是quart.net是经过许多大项 ...

  6. Quartz.net开源作业调度框架使用详解

    前言 quartz.net作业调度框架是伟大组织OpenSymphony开发的quartz scheduler项目的.net延伸移植版本.支持 cron-like表达式,集群,数据库.功能性能强大更不 ...

  7. quartz.net 时间表达式----- Cron表达式详解

    序言 Cron表达式:就是用简单的xxoo符号按照一定的规则,就能把各种时间维度表达的淋漓尽致,无所不在其中,然后在用来做任务调度(定时服务)的quart.net中所认知执行,可想而知这是多么的天衣无 ...

  8. Quartz.NET Windows 服务示例

    想必大家在项目中处理简单的后台持续任务或者定时触发任务的时候均使用 Thread 或者 Task 来完成,但是项目中的这种需求一旦多了的话就得将任务调度引入进来了,那今天就简单的介绍一下 Quartz ...

  9. [Quartz笔记]玩转定时调度

    简介 Quartz是什么? Quartz是一个特性丰富的.开源的作业调度框架.它可以集成到任何Java应用. 使用它,你可以非常轻松的实现定时任务的调度执行. Quartz的应用场景 场景1:提醒和告 ...

  10. 关于Quartz.NET作业调度框架的一点小小的封装,实现伪AOP写LOG功能

    Quartz.NET是一个非常强大的作业调度框架,适用于各种定时执行的业务处理等,类似于WINDOWS自带的任务计划程序,其中运用Cron表达式来实现各种定时触发条件是我认为最为惊喜的地方. Quar ...

随机推荐

  1. Unity3D 打包成Exe文件

    Unity发布后一般都会一个exe文件和_data文件以及UnityPlayer.dll,如果把这三个文件整合成一个exe就可以(装逼)了 首先打开Winrar将这三个压缩: 压缩文件名设置为需要启动 ...

  2. Hibernate框架 初识 ORM概念

    Hibernate概述 Hibernate是一个ORM(对象关系映射)映射框架,它的核心思想就是在底层对JDBC进行了一次封装. 什么是框架 IT语境中的框架,特指为解决一个开放性问题而设计的具有一定 ...

  3. Flutter路由(一)

    第一点:push使用 1.pushNamed——Navigator.of(context).pushNamed('routeName') Navigator.of(context).pushNamed ...

  4. Arouter核心思路和源码

    前言 阅读本文之前,建议读者: 对Arouter的使用有一定的了解. 对Apt技术有所了解. Arouter是一款Alibaba出品的优秀的路由框架,本文不对其进行全面的分析,只对其最重要的功能进行源 ...

  5. 在windows上远程访问服务器jupyter notebook

    需求: 之前在服务器上只能运行完整的python文件,而不能实现jupyter notebook的交互模式,通过在本地浏览器上远程访问服务器上的jupyter notebook,这样不就能有一个很棒的 ...

  6. 20个python项目--图片转字符画

    转自实验楼:https://www.shiyanlou.com/courses/370/learning/?id=1191 代码: # -*- coding:utf-8 -*- from PIL im ...

  7. 修改了Mysql密码后连接不到服务且无报错信息解决方法以及修改密码方法

    安装MYSQL后更改了root的密码后用 net start mysql 启动时出现:无法启动,无报错信息 使用以下命令:1.管理员方式cmd进入mysql安装目录的bin目录下2.执行命令:mysq ...

  8. 文件的上传(1)(表单上传和ajax文件异步上传)

    文件的上传(表单上传和ajax文件异步上传) 项目中用户上传总是少不了的,下面就主要的列举一下表单上传和ajax上传!注意: context.Request.Files不适合对大文件进行操作,下面列举 ...

  9. excel常用公式--计算统计类

    Count/Countif/Countifs:条件计数. 注:count只能对数值进行统计 sum/sumif/sumifs:条件求和.   Average/Averageifs:  返回参数的平均值 ...

  10. (5.1.5)引擎管理——多服务器管理之中央管理服务器(CMS)

    关键词:中央管理服务器,CMS,多服务器管理 中央管理服务器 -[1]打开 视图->已注册的服务器 [2]注册中央管理服务器 右击中央管理器->注册中央管理服务器 这里输入IP.主机名都可 ...