1.Quartz的作用 定时自动执行任务
2.预备 相关包官方网站 
1 2 quartz2.2.1 quartz-jobs2.2.1 
 
POM文件
1 2 3 4 5 6 7 8 9 10 <dependency>     <groupId>org.quartz-scheduler</groupId>     <artifactId>quartz</artifactId>     <version>2.2.1</version> </dependency> <dependency>      <groupId>org.quartz-scheduler</groupId>      <artifactId>quartz-jobs</artifactId>      <version>2.2.1</version>  </dependency>    
 
3.Quartz核心 3.1.Job接口 被调度的任务,只有一个方法execute(JobExecutionContext xontext),Job运行时的信息保存在JobDataMap中
3.2.JobDetail类 实现Job接口,用来描述Job的相关信息,包含Name,Group,JobDataMap等
3.3 JobExecutionContext类 定时程序执行的run-time的上下文环境,用于得到Job的名字、配置的参数等
3.3 JobDataMap类 用来描述一个作业的参数,参数可以为金和基本类型或者某个对象的引用
3.3 JobListener接口 监听作业状态
3.3 TriggaerListener接口 监听触发器状态
3.3 JobStore 3.3.Tigger抽象类 触发器,描述执行Job的触发规则,有SimpleTrigger和CronTrigger两个子类
3.3.1.SimpleTrigger类 继承自Trigger类,每隔xx毫秒/秒执行一次,主要实现固定一次或者固定时间周期类任务的触发
3.3.2.CronTrigger类 继承自Trigger类,使用Cron表达式,实现各种复杂时间规则调度方案,如每天的某个时间,或每周的某几天触发执行之类
3.4.Calendar包 一些日历特定时间点的集合,包内包含以下几个类
3.4.1 BaseCalendar类 3.4.2 AnnualCalendar类 排除每一年中指定的一天或者多天
3.4.3 CalendarComparator类 3.4.4 CronCalendar类 使用表达式排除某时间段不执行
3.4.5 DailyCalendar类 指定的时间范围内每天不执行
3.4.6 HolidayCalendar类 排除节假日
3.4.7 MonthlyCalendar类 配出月份中的数天
3.4.8 WeeklyCalendar类 排除没周中的一天或者多天
3.5.Scheduler类 任务调度器,代表一个Quartz独立容器。
Scheduler可以将JobDetail和Trigger绑定,当Trigger触发时,对应的Job就会被执行,Job和Trigger是1:n(一对多)的关系
3.6Misfire类 错误的任务,本该执行单没有执行的任务调度
4.实现 1.单任务实现 1.定义一个任务,新建任务类继承自Job类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class DemoJob implements Job { @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date())); } } 
 
2.新建类执行这个任务(SimpleTrigger)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package com; import java.util.Date; import org.quartz.DateBuilder; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; public class QuartzDemo { public void simpleRun() throws SchedulerException { SchedulerFactory factory = new StdSchedulerFactory();       Date runTime = DateBuilder.evenSecondDateAfterNow();   JobDetail jobDetail = JobBuilder.newJob(DemoJob.class) .withIdentity("demo_job", "demo_group") .build(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("demo_trigger", "demo_group") .startAt(new Date()) .withSchedule( SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(1) .withRepeatCount(5) ).build(); Scheduler scheduler = factory.getScheduler(); scheduler.scheduleJob(jobDetail,trigger); System.out.println(jobDetail.getKey() + " 运行在: " + runTime);    scheduler.start();   } public static void main(String[] args) { QuartzDemo demo = new QuartzDemo(); try { demo.simpleRun(); } catch (SchedulerException e) { e.printStackTrace(); } } } 
 
2.多任务实现 
测试任务类 新建两个DemoJonOne和DemoJobTwo,都实现Job接口,内容如下 
 
1 2 3 4 @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date())+" Runed "+getClass().getName()); } 
 
2.新建QuartzUtil类,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package com; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; public class QuartzUtil { private final static String JOB_GROUP_NAME = "QUARTZ_JOBGROUP_NAME"; private final static String TRIGGER_GROUP_NAME = "QUARTZ_TRIGGERGROUP_NAME"; public static void addJob(String jobName, String triggerName, Class<? extends Job> jobClass, int seconds) throws SchedulerException { SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sche = sf.getScheduler(); JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, JOB_GROUP_NAME).build(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity(triggerName, TRIGGER_GROUP_NAME) .startNow() .withSchedule( SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(seconds) .repeatForever() ).build(); sche.scheduleJob(jobDetail, trigger); sche.start(); } public static void main(String[] args) { try { QuartzUtil.addJob("job1", "trigger1", DemoJobOne.class, 2); QuartzUtil.addJob("Job2", "trigger2", DemoJobTwo.class, 5); } catch (SchedulerException e) { e.printStackTrace(); } } } 
 
以上方法属于手动调用,如果是web项目中就不同了 添加POM
1 2 3 4 5 <dependency>   <groupId>javax.servlet</groupId>   <artifactId>servlet-api</artifactId>   <version>2.5</version> </dependency> 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import org.quartz.SchedulerException; import com.DemoJobOne; import com.DemoJobTwo; import com.QuartzUtil; public class InitServlet extends HttpServlet { private static final long serialVersionUID = 8507188690597926975L; public void init() throws ServletException { try { QuartzUtil.addJob("job1", "trigger1", DemoJobOne.class, 2); QuartzUtil.addJob("Job2", "trigger2", DemoJobTwo.class, 5); } catch (SchedulerException e) { e.printStackTrace(); } } } 
 
2.注册servlet
1 2 3 4 5 6 7 8 9 10 11 <servlet>   <servlet-name>InitServlet</servlet-name>   <servlet-class>servlet.InitServlet</servlet-class>      <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping>   <servlet-name>InitServlet</servlet-name>   <url-pattern>/InitServlet</url-pattern> </servlet-mapping> 
 
3.复杂规则任务调度(CronTrigger) 在每分钟的1-30秒执行示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com; import org.quartz.CronScheduleBuilder; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; public class CronTriggerDemo { public static void main(String[] args) throws SchedulerException { SchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); JobDetail job = JobBuilder .newJob(DemoJobOne.class) .withIdentity("job","group") .build(); Trigger trigger = TriggerBuilder .newTrigger() .withIdentity("trigger", "group") .startNow().withSchedule( CronScheduleBuilder .cronSchedule("1-30 * * * * ?") ).build(); scheduler.scheduleJob(job,trigger); scheduler.start(); } } 
 
5.Cron表达式 规则 格式
 
s:seconds,取值0-59,允许- * /;
M:minutes,取值0-59,允许- * /;
h:hour,取值0-23,允许- * /;
d:day of month,取值1-31,允许- * ? / L W;
m:month,取值1-12/JAN-DEC,允许- * /;
w:day of week,取值1-7/SUN-SAT,允许- * ? / L #;
y:year,可选,取值empty、1970-2099,允许- * /;
符号解释 、 指定枚举值,如在秒字段使用10、12,则表示只有第10秒和第12秒执行 - 指定区间范围,配合使用,如在小时字段使用10-12,表示在10、11、12时都会触发
* 代表所有值,单独使用,如在秒字段使用,表示每秒触发
? 代表不确定值,单独使用,不用关心的值
/ 用于递增触发,配合使用,n/m,从n开始,每次增加m,如在秒字段设置5/15,表示从第5秒开始,每15秒触发一次
L 表示最后,单独使用,如在秒字段使用,代表第59秒触发,如果在前面加上数字,则表示该数据的最后一个,如在周字段使用6L,则表示本月最后一个周五 W 表示最近的工作日,不会跨月,比如30W,30号是周六,则不会顺延至下周一来执行,如在月字段使用15W,则表示到本月15日最近的工作日(周一到周五) # 用来指定x的第n个工作日,如在周字段使用6#3则表示该月的第三个星期五
月取值 一月:JAN/0 二月:FEB/1 三月:MAR/2 四月:APR/3 五月:MAY/4 六月:JUN/5 七月:JUL/6 八月:AUG/7 九月:SEP/8 十月:OCT/9 十一月:NOV/10 十二月:DEC/11
周取值 周日:SUN/1 周一:MON/2 周二:TUE/3 周三:WED/4 周四:THU/5 周五:FRI/6 周六:SAT/7
示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 0/20 * * * * ? 每20秒执行一次 1-30 * * * * ? 在1-30秒执行 15 0/2 * * * ? 偶数分钟的第15秒执行 0 0/2 8-17 * * ? 从8时到17时 ,每个偶数分钟执行一次 0 0/3 17-23 * * ? 从17时到23时,每3分钟运行一次 0 0 10am 1,15 * ? 每个月的1号和15号的上午10点 运行 0,30 * * ? * MON-FRI 周一至周五,每30秒运行一次 0,30 * * ? * SAT,SUN 周六、周日,每30秒运行一次 0 0 12 * * ? 每天12点触发 0 15 10 ? * * 每天10点15分触发 0 15 10 * * ? 每天10点15分触发 0 15 10 * * ? * 每天10点15分触发 0 15 10 * * ? 2005 2005年每天10点15分触发 0 * 14 * * ? 每天下午的 2点到2点59分每分触发 0 0/5 14 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发) 0 0/5 14,18 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发) 每天下午的 18点到18点59分(整点开始,每隔5分触发) 0 0-5 14 * * ?  每天下午的 2点到2点05分每分触发 0 10,44 14 ? 3 WED 3月分每周三下午的 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 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期五的10点15分触发 0 15 10 ? * 6#3 每月的第三周的星期五开始触发 0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次 0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节) 
 
6.Spring整合Quartz 需要Spring-context-support包支持,POM如下
1 2 3 4 5 <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-context-support</artifactId>     <version>4.3.5.RELEASE</version> </dependency> 
 
新建两种Job测试类–>DemoSimpleJob类和DemoCronJob类,并继承自QuartzJobBean,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class DemoJob extends QuartzJobBean {     @Override     protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {         System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date()) + " 输出自:" + getClass().getName());     } } 
 
配置spring bean如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <?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:context="http://www.springframework.org/schema/context"     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"     xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-4.3.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">                    <bean id="demoCronJob"         class="org.springframework.scheduling.quartz.JobDetailFactoryBean">         <property name="jobClass" value="com.DemoCronJob" />     </bean>     <bean id="demoSimpleJob"         class="org.springframework.scheduling.quartz.JobDetailFactoryBean">         <property name="jobClass" value="com.DemoSimpleJob" />     </bean>               <bean id="simpleTrigger"         class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">         <property name="jobDetail" ref="demoSimpleJob" />         <property name="startDelay" value="1000" />           <property name="repeatInterval" value="2000" />       </bean>     <bean id="cornTrigger"         class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">         <property name="jobDetail" ref="demoCronJob" />         <property name="cronExpression" value="1-30 * * * * ?" />     </bean>          <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">         <property name="triggers">             <list>                 <ref bean="cornTrigger" />                 <ref bean="simpleTrigger" />             </list>         </property>     </bean> 
 
启动
1 2 3 4 5 6 7 8 9 10 11 package com; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Demo {     public static void main(String[] args) {         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");     } } 
 
有待补充