1 Quartz简介
Quartz是执行定时任务的框架,由开源组织OpenSymphony在Job scheduling领域的开源项目,完全由java开发.
组成:
- Job,JobDetail
Job具体的业务逻辑类,JobDetail业务实例,实现多任务. - Trigger
JobDetail触发器,即执行任务的触发条件(设定的时间,时间间隔和执行次数).包括SimpleTrigger和CronTrigger,SimpleTrigger为简单触发条件,如执行时间和执行次数,CronTrigger可进一步设定执行周期,年月日时段. - Scheduler
调度器,通过触发器执行业务.
2 组件功能
2.1 Job
Job是Quartz中的一个接口,只有execute方法,在这个方法中编写业务逻辑.
public interface Job{
void execute(JobExecutionContext var1) throws JobExecutionException;
}
2.2 JobDetail
可理解为Job的实例,每调用一个Job,通过JobDetail创建一个新的实例,Scheduler对JobDetail进行调度,可实现多定时任务.
- JobBuilder
实例化JobDetail,创建新的Job执行任务.
2.3 JobExecutionContext
包含Job的详细参数,当Scheduler执行一个Job时,将JobExecutionContext传递给Job中的execute方法.
2.4 Trigger
触发器,满足触发器条件,执行任务.
- TriggerBuilder
实例化触发器. - SimpleTrigger
触发时间规则设定器,包括指定时间段内执行任务的次数. - CronTrigger
触发时间规则设定器,基于日历的作业调度,可指定执行日期,日历规则:
秒 分 小时 日 月 周 年
序号 | 时间字段 | 允许值 | 允许特殊字符 |
---|---|---|---|
1 | 秒 | 0-59 | -*/ |
2 | 分 | 0-59 | -*/ |
3 | 小时 | 0-23 | -*/ |
4 | 日 | 1-31 | -*?/LWC |
5 | 月份 | 1-12或JAN-DEC | -*/ |
6 | 周 | 1-7或SUN-SAT | -*?/LC# |
7 | 年 | (可选)1970-2099 | -*/ |
3 Usage
3.1 pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
3.2 定时任务操作
package com.prjname.service;
import java.util.Map;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(rollbackFor = Exception.class)
public class TimerService{
@Autowired
private Scheduler scheduler;
public String buildTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
String timeCycle = taskInfos.get("taskTimeCycle").toString();
String classNameStr = taskInfos.get("className").toString();
Class className = Class.forName(classNameStr);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(timeCycle);
JobDetail jobDetail = JobBuilder.newJob(className)
.withIdentity(name, group)
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(name, group)
.startNow()
.withSchedule(scheduleBuilder)
.build();
scheduler.scheduleJob(jobDetail, trigger);
return "新建并启动5秒的定时任务";
}
public String pauseTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail == null){
return "定时任务不存在";
}
scheduler.pauseJob(jobKey);
return "暂停定时任务"+name;
}
public String resumeTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
JobKey jobKey= new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail == null){
return "定时任务不存在";
}
scheduler.resumeJob(jobKey);
return "恢复定时任务:"+name;
}
public String deleteTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail == null){
return "定时任务不存在";
}
scheduler.deleteJob(jobKey);
return "删除定时任务:"+name;
}
}
3.2.1 新建定时任务
public String buildTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
String timeCycle = taskInfos.get("taskTimeCycle").toString();
String classNameStr = taskInfos.get("className").toString();
Class className = Class.forName(classNameStr);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(timeCycle);
JobDetail jobDetail = JobBuilder.newJob(className)
.withIdentity(name, group)
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(name, group)
.startNow()
.withSchedule(scheduleBuilder)
.build();
scheduler.scheduleJob(jobDetail, trigger);
return "新建并启动5秒的定时任务";
}
3.2.2 停止定时任务
public String pauseTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail == null){
return "定时任务不存在";
}
scheduler.pauseJob(jobKey);
return "暂停定时任务"+name;
}
3.2.3 重启定时任务
public String resumeTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
JobKey jobKey= new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail == null){
return "定时任务不存在";
}
scheduler.resumeJob(jobKey);
return "恢复定时任务:"+name;
}
3.2.4 删除定时任务
public String deleteTimerTask(Map taskInfos) throws Exception{
String name = taskInfos.get("taskName").toString();
String group = taskInfos.get("taskGroup").toString();
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail == null){
return "定时任务不存在";
}
scheduler.deleteJob(jobKey);
return "删除定时任务:"+name;
}
3.2.5 定时任务传参
新建定时任务时,可以传递参数,使用usingJobData属性,操作如下:
JobDetail jobDetail = JobBuilder.newJob(className)
.withIdentity(name, group)
.usingJobData("params", params)
.build();
3.3 定时任务执行业务逻辑
该部分为定时任务定期执行的业务逻辑,本次以打印时间为例,每隔5秒,打印一次当前时间。
package com.prjname.timer;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class TestTimer extends QuartzJobBean{
static Logger logger = LoggerFactory.getLogger(TestTimer.class);
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String time = sdf.format(date);
logger.info("定时时间:{}",time);
}
}
3.4 控制器
package com.prjname.controller;
import com.xhwl.service.TimerService;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@CrossOrigin(origins="*", maxAge=3600)
@RestController
@RequestMapping("/api/v1")
public class TimerController{
static Logger logger = LoggerFactory.getLogger(TimerController.class);
@Autowired
private TimerService timerService;
@RequestMapping(value="/timer-task-creation", method=RequestMethod.POST)
public Map createTimerTask(@RequestBody Map params){
Map returnMap = new HashMap();
try{
String taskName = params.get("taskName").toString();
String taskGroup = params.get("taskGroup").toString();
String taskTimeCycle = params.get("taskCycle").toString();
if(!taskName.equals("")|!taskGroup.equals("")|!taskTimeCycle.equals("")){
Map<String, String> taskInfos = new HashMap<String, String>();
taskInfos.put("taskName", taskName);
taskInfos.put("taskGroup", taskGroup);
taskInfos.put("taskTimeCycle", taskTimeCycle);
taskInfos.put("className", "com.prjname.timer.TestTimer");
String returnStr = timerService.startTimerTask(taskInfos);
returnMap.put("code",200);
returnMap.put("infos",returnStr);
return returnMap;
}else{
returnMap.put("code",200);
returnMap.put("infos","检查参数");
return returnMap;
}
}catch(Exception e){
e.printStackTrace();
}
returnMap.put("code",400);
returnMap.put("infos","检查参数");
return returnMap;
}
@RequestMapping(value="/timer-task-pause", method=RequestMethod.POST)
public Map pauseTimerTask(@RequestBody Map params){
Map returnMap = new HashMap();
try{
String taskName = params.get("taskName").toString();
String taskGroup = params.get("taskGroup").toString();
if(!taskName.equals("")|!taskGroup.equals("")){
String returnStr = timerService.pauseTimerTask(params);
returnMap.put("code", 200);
returnMap.put("infos", returnStr);
return returnMap;
}else{
returnMap.put("code", 400);
returnMap.put("infos", "检查参数");
return returnMap;
}
}catch(Exception e){
e.printStackTrace();
}
return returnMap;
}
}
【参考文献】
[1]https://www.jb51.net/article/160555.htm
[2]https://blog.csdn.net/noaman_wgs/article/details/80984873
[3]https://www.jianshu.com/p/056281e057b3
[4]https://www.cnblogs.com/knowledgesea/p/4705796.html
[5]https://www.cnblogs.com/bevis-byf/p/10087032.html