一、组成:
Quartz 设计的核心类包括 Scheduler, Job 以及 Trigger。其中,Job 负责定义需要执行的任务,Trigger 负责设置调度策略,Scheduler 将二者组装在一起,并触发任务开始执行。
1、job:使用者只需要创建一个 Job 的继承类,实现 execute 方法
2、JobDetail 负责封装 Job 以及 Job 的属性,并将其提供给 Scheduler 作为参数。每次 Scheduler 执行任务时,首先会创建一个 Job 的实例,然后再调用 execute 方法执行。Quartz 没有为 Job 设计带参数的构造函数,因此需要通过额外的 JobDataMap 来存储 Job 的属性。JobDataMap 可以存储任意数量的 Key,Value 对。存:
JobDataMap jobDataMap = jobDetail.getJobDataMap(); jobDataMap .put("myDescription", "my job description"); jobDataMap .put("myValue", 1998); ArrayList<String> list = new ArrayList<String>(); list.add("item1"); jobDataMap .put("myArray", list);取:
@Override public void execute(JobExecutionContext context) throws JobExecutionException { //从context中获取instName,groupName以及dataMap String instName = context.getJobDetail().getName(); String groupName = context.getJobDetail().getGroup(); JobDataMap dataMap = context.getJobDetail().getJobDataMap(); //从dataMap中获取myDescription,myValue以及myArray String myDescription = dataMap.getString("myDescription"); int myValue = dataMap.getInt("myValue"); ArrayList<String> myArray = (ArrayListlt;Strin>) dataMap.get("myArray"); System.out.println(" Instance =" + instName + ", group = " + groupName + ", description = " + myDescription + ", value =" + myValue + ", array item0 = " + myArray.get(0)); }
二、代码简单实现:比如这里启动两个定时Job
1、pom:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- quartz --> <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>2、启动类:
package com.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class JobStart { public static void main(String[] args) { SpringApplication.run(JobStart.class, args); } }3、两个job:
package com.demo.job; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * * @Description: 需要执行的内容 */ public class MyJob implements Job{ @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd : hh:mm:ss"); String str = dateFormat.format(new Date()); System.err.println("MyJob当前时间:"+str); } } package com.demo.job; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * * @Description: 需要执行的内容 */ public class MyJob1 implements Job{ @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd : hh:mm:ss"); String str = dateFormat.format(new Date()); System.out.println("MyJob1当前时间:"+str); } }4、触发器:
package com.demo.job; import java.util.Date; import javax.annotation.PostConstruct; import org.quartz.CronScheduleBuilder; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.quartz.impl.StdSchedulerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cglib.proxy.Factory; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; /** * @Description:job触发器,触发MyJob执行 */ @Component public class JobScheduler { @Autowired private Scheduler scheduler; //在@PostConstruct之前执行 @Bean public Scheduler scheduler() throws SchedulerException{ SchedulerFactory schedulerFactoryBean = new StdSchedulerFactory(); return schedulerFactoryBean.getScheduler(); } @PostConstruct public void init() throws SchedulerException{ System.err.println("执行"); //创建两个job //没10s运行一次MyJob String cron = "0/10 0/1 * * * ? "; addJob(cron,MyJob.class,"key1"); //没5s运行一次MyJob1 String cron1 = "0/5 0/1 * * * ? "; addJob(cron1,MyJob1.class,"key2"); scheduler.start(); } private void addJob(String cron, Class<? extends Job> clazz,String jobId) throws SchedulerException { //创建一个jobDetail的实例,将该实例与目标Job Class绑定 JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(JobKey.jobKey(jobId)).build(); //cron表达式 TriggerBuilder<Trigger> builder = TriggerBuilder.newTrigger() .withIdentity(TriggerKey.triggerKey(jobId)); //现在执行 builder.startAt(new Date()); Trigger trigger = builder.withSchedule(CronScheduleBuilder.cronSchedule(cron)).build(); //创建schedule实例 scheduler.scheduleJob(jobDetail,trigger); } }@PostConstruct注解的方法全局只会执行一次,故可以充当main方法,去触发job。这里在init方法中创建了两个job。
运行启动类:
三、动态定时:
quartz支持job的增删改:
新增一个Job:
private void addScheduleJob(Job job) throws SchedulerException { String jobGroup = String.format("group-%s", job.getJobName()); JobDetail jobDetail = JobBuilder.newJob(ExecuteJob.class) .withIdentity(JobKey.jobKey(String.format("job-%s", job.getId()), jobGroup)) .build(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); jobDataMap.put("jobId", job.getId()); jobDataMap.put("processId", job.getProcessId()); TriggerBuilder<Trigger> builder = TriggerBuilder.newTrigger() .withIdentity(TriggerKey.triggerKey(String.format("trigger-%s", job.getId()), jobGroup)); if (new Date().before(job.getStartTime())) { builder.startAt(job.getStartTime()); } else { builder.startNow(); } Trigger trigger = builder.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).build(); scheduler.scheduleJob(jobDetail, trigger); }删除一个job:
/** * 删除job调度任务 */ public void deleteJob(Job job) throws SchedulerException { String jobGroup = String.format("group-%s", job.getJobName()); String jobName = String.format("job-%s", job.getId()); String triggerName = String.format("trigger-%s", job.getId()); TriggerKey triggerKey = new TriggerKey(triggerName, jobGroup); JobKey jobKey = new JobKey(jobName, jobGroup); scheduler.pauseTrigger(triggerKey); scheduler.unscheduleJob(triggerKey); scheduler.deleteJob(jobKey); logger.info("删除job调度"); }修改一个job:
/** * 修改job调度任务 */ public void updateJob(Job job) throws SchedulerException { String jobGroup = String.format("group-%s", job.getJobName()); //String jobName = String.format("job-%s", job.getId()); String triggerName = String.format("trigger-%s", job.getId()); TriggerKey triggerKey = new TriggerKey(triggerName, jobGroup); TriggerBuilder<Trigger> builder = TriggerBuilder.newTrigger() .withIdentity(TriggerKey.triggerKey(String.format("trigger-%s", job.getId()), jobGroup)); if (new Date().before(job.getStartTime())) { builder.startAt(job.getStartTime()); } else { builder.startNow(); } Trigger trigger = builder.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).build(); scheduler.rescheduleJob(triggerKey, trigger); logger.info("修改Job调度"); }
这里把定时的相关参数全部放在数据库中, 见下一篇博客。