一、组成:
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调度");
}
这里把定时的相关参数全部放在数据库中, 见下一篇博客。