Spring Quartz实现任务调度
任务调度
在企业级应用中,经常会制定一些“计划任务”,即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发、线程池维护、运行时间规则解析、运行现场的保护以恢复等方面 Quartz框架是一个开源的企业级任务调度服务,已经被作为任务调度的良好解决方案.
Quartz框架核心
Quartz对任务调度进行了高度抽象,提出了3个核心概念,并在org.quartz包中通过接口和类进行了描述
任务:就是执行的工作内容。Quartz提供Job接口来支持任务定义
触发器:定义触发Job执行的时间触发规则。Quartz提供Trigger类及其子类支持触发器功能
调度器:Quartz提供了Scheduler接口,将工作任务和触发器绑定,保证任务可以在正确的时间执行
运行环境
任务调度
任务执行
任务持久化
事务
集群
监听器和插进
Quartz案例
1.找到Quartz框架的jar包
2.开始创建entity实体层定义任务的模板
package cn.entity; public class Plan { //时间 private String date; //任务 private String task; public Plan() { super(); } public Plan(String date, String task) { super(); this.date = date; this.task = task; } @Override public String toString() { return "Plan [date=" + date + ", task=" + task + "]"; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getTask() { return task; } public void setTask(String task) { this.task = task; } }
3.定制一个泛型集合用户存储多个Plan对象,提供一个方法读取该泛型集合中的data
package cn.service; import java.util.ArrayList; import java.util.List; import cn.entity.Plan; /** * 提醒服务类 * @author * */ public class RemindService { //01.创建一个集合,并且方法返回值是一个集合类型 public List<Plan> getPlansForToday(){ List<Plan> list=new ArrayList<Plan>(); Plan plan1=new Plan("2016年12月16日","2016最后一个月"); Plan plan2=new Plan("2016年12月18日","Quartz"); list.add(plan1); list.add(plan2); return list; } //02.用来打印集合中提醒内容的方法 public void printMessage(){ List<Plan> list = getPlansForToday(); for (Plan plan : list) { //单个的plan System.out.println("计划的时间"+plan.getDate()+"\t计划内容"+plan.getTask()); } } }
4.提醒业务类
package cn.quartz; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import cn.service.RemindService; /** * 提醒业务 * @author * */ //让一个普通类变成计划 public class RemindJob implements Job { //植入service 对象 private RemindService service=new RemindService(); @Override public void execute(JobExecutionContext context) throws JobExecutionException { service.printMessage(); } public RemindService getService() { return service; } public void setService(RemindService service) { this.service = service; } }
Job接口中只有一个 execute()方法,在实现类中 实现该方法以执行具体任务。
5.真正的任务对象和触发器对象
package cn.test; import java.util.Date; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; 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.TriggerKey; import org.quartz.impl.StdSchedulerFactory; import cn.quartz.RemindJob; public class MyQuartzTest { public static void tool() throws SchedulerException, InterruptedException{ //第一步构建Job JobDetail job = JobBuilder.newJob(RemindJob.class)// .withIdentity("job1", "group1")// .build(); //第二步创建Trigger //第一种方式 控制不太好 /* Date runTime = DateBuilder.evenMinuteDate(new Date(System.currentTimeMillis())); Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")// .startAt(runTime).build();*/ //第二种方式 不太好 /*Trigger trigger = TriggerBuilder.newTrigger() .withIdentity(TriggerKey.triggerKey("myTrigger", "myTriggerGroup")) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(2) .repeatForever()) .startAt(new Date(System.currentTimeMillis()+2000)) .build();*/ //第三步绑定 JOb和Trigger // First we must get a reference to a scheduler //创建调度者工厂 SchedulerFactory sf = new StdSchedulerFactory(); //创建一个调度者 Scheduler sched = sf.getScheduler(); //注册并进行调度 sched.scheduleJob(job, trigger); //启动调度 sched.start(); /*Thread.sleep(3000); * //关闭调度 sched.shutdown();*/ } public static void main(String[] args) throws SchedulerException, InterruptedException { tool(); System.out.println("呵呵"); } }
第一种方式:
第二种方式:
6.使用CronTrigger
CronTrigger也是Trigger的子类
CronTrigger和SimpleTrigger的对比
CronTrigger允许用户更精准地控制任务的运行日期和时间,而不仅仅是定义工作的频度
CronTrigger通过Cron表达式定义准确的运行时间点。创建CronTrigger的语法如下:
7.Cron表达式
要使用CronTrigger,必须掌握Cron表达式
Cron表达式由6~7个由空格分隔的时间元素组成。第7个元素可选
Cron表达式的每个字段,都可以显式地规定一个值(如49)、一个范围(如1-6)、一个列表(如1,3,5)或者一个通配符(如*)
8.Cron表达式有几个特殊的字符,说明如下
“ - ”:中划线,表示一个范围
“ , ”:使用逗号间隔的数据,表示一个列表
“ * ”:表示每一个值,它可以用于所有字段。例如:在小时字段表示每小时
“ ? ”:该字符仅用于“月份中的哪一天”字段和“星期几”字段,表示不指定值
“ / ”:通常表示为x/y,x为起始值,y表示值的增量。
“ L ”:表示最后一天,仅在日期和星期字段中使用
“ # ”:只能用于“星期几”字段,表示这个月的第几个周几。例如:“6#3”指这个月第三个周五
9.Cron表达式案例
测试:
package cn.test; import java.util.Date; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; 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.TriggerKey; import org.quartz.impl.StdSchedulerFactory; import cn.quartz.RemindJob; public class MyQuartzTest { public static void tool() throws SchedulerException, InterruptedException{ //第一步构建Job JobDetail job = JobBuilder.newJob(RemindJob.class)// .withIdentity("job1", "group1")// .build(); //第二步创建Trigger /** * 2016年每月的第三个星期六上午10:18触发 0 18 10 ? * 6#3 2016 */ CronTrigger trigger=TriggerBuilder.newTrigger()// .withIdentity("myTrigger", "myTriggerGroup")// .withSchedule(CronScheduleBuilder.// cronSchedule("0 18 10 ? * 6#3 2016")).build(); //第三步绑定 JOb和Trigger // First we must get a reference to a scheduler //创建调度者工厂 SchedulerFactory sf = new StdSchedulerFactory(); //创建一个调度者 Scheduler sched = sf.getScheduler(); //注册并进行调度 sched.scheduleJob(job, trigger); //启动调度 sched.start(); } public static void main(String[] args) throws SchedulerException, InterruptedException { tool(); System.out.println("呵呵"); } }