前言:我想实现的是延迟发送,但是Quartz也可以实现这一需求,而且还可以通过数据库查看哪些延迟任务没有执行成功,今天主要来说一下Quartz。
延迟发送的方法包括:
- 手动无线循环;
- ScheduledExecutorService;
- DelayQueue;
- Redis zset 数据判断的方式;
- Redis 键空间通知的方式;
- Netty 提供的 HashedWheelTimer 工具类;
- RabbitMQ 死信队列;
- RabbitMQ 延迟消息插件 rabbitmq-delayed-message-exchange;
- Spring Scheduled;
- Quartz。
quartz需要数据库,需要创建表
#1 保存已经触发的触发器状态信息
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
#2 存放暂停掉的触发器表表
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
#3 调度器状态表
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
#4 存储程序的悲观锁的信息(假如使用了悲观锁)
DROP TABLE IF EXISTS QRTZ_LOCKS;
#5 简单的触发器表
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
#6 存储两种类型的触发器表
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
#7 定时触发器表
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
#8 以blob 类型存储的触发器
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
#9 触发器表
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
#10 job 详细信息表
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
#11 日历信息表
DROP TABLE IF EXISTS QRTZ_CALENDARS;
#job 详细信息表
CREATE TABLE QRTZ_JOB_DETAILS
(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
#触发器表
CREATE TABLE QRTZ_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
#简单的触发器表,包括重复次数,间隔,以及已触发的次数
CREATE TABLE QRTZ_SIMPLE_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
#定时触发器表,存储 cron trigger,包括 cron 表达式和时区信息
CREATE TABLE QRTZ_CRON_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(200) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
#存储calendarintervaltrigger和dailytimeintervaltrigger两种类型的触发器
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
#以blob 类型存储的触发器
CREATE TABLE QRTZ_BLOB_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
#日历信息表, quartz可配置一个日历来指定一个时间范围
CREATE TABLE QRTZ_CALENDARS
(
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
#存放暂停掉的触发器表表
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
# 存储与已触发的 trigger 相关的状态信息,以及相联 job 的执行信息
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
# 调度器状态表
CREATE TABLE QRTZ_SCHEDULER_STATE
(
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
# 存储程序的悲观锁的信息
CREATE TABLE QRTZ_LOCKS
(
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
SpringBoot集成Quartz引入依赖:
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<!-- quartz-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.19</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<version>2.5.4</version>
</dependency>
添加yml配置
spring:
#定时配置
quartz:
#相关属性配置
properties:
org:
quartz:
scheduler:
instanceName: local-scheduler-svc
instanceId: AUTO
jobStore:
#表示 quartz 中的所有数据,比如作业和触发器的信息都保存在内存中(而不是数据库中)
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
# 驱动配置
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 表前缀
tablePrefix: QRTZ_
#是否为集群
isClustered: false
clusterCheckinInterval: 10000
useProperties: false
dataSource: quartzDs
#线程池配置
threadPool:
class: org.quartz.simpl.SimpleThreadPool
#线程数
threadCount: 10
#优先级
threadPriority: 5
#线程继承上下文类加载器的初始化线程
threadsInheritContextClassLoaderOfInitializingThread: true
#数据库方式
job-store-type: JDBC
#初始化表结构
jdbc:
initialize-schema: NEVER
创建实体类,用于传递任务信息
import lombok.Data;
import java.util.Date;
import java.util.Map;
/**
* @Author majinzhong
* @Date 2024/5/9 15:42
* @Version 1.0
*/
@Data
public class JobInfo {
//任务名称
private String jobName;
//任务组
private String jobGroup;
//任务执行信息(在用户定时远程调用接口的时候,我们可以接口信息封装到这个Map中)
private Map<String, Object> jsonParams;
//定时任务的cron表达式
private String cron;
//定制执行任务的时区
private String timeZoneId;
//定时器时间(目前没用上)
private Date triggerTime;
}
创建任务执行类HttpRemoteJob实现Job接口,重写execute()方法
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.dreampen.service.JobService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Objects;
/**
* @Author majinzhong
* @Date 2024/5/9 15:46
* @Version 1.0
*/
@DisallowConcurrentExecution
public class HttpRemoteJob implements Job {
@Autowired
JobService jobService;
//日志
private static final Logger log = LoggerFactory.getLogger(HttpRemoteJob.class);
@Override
public void execute(JobExecutionContext context)throws JobExecutionException {
//用于发送网络请求
HttpURLConnection connection = null;
//用于接收请求返回的结果
BufferedReader bufferedReader = null;
//获取任务Description述,之前我们把接口请求的信息放在Description里面了
String jsonParams = context.getJobDetail().getDescription();
if (StringUtils.isEmpty(jsonParams)){
return;
}
//解析Description,获取请求url
JSONObject jsonObj= (JSONObject) JSONObject.parse(jsonParams);
String callUrl = jsonObj.getString("callUrl");
if(StringUtils.isEmpty(callUrl)) {
return;
}
try {
//编辑请求信息
URL realUrl = new URL(callUrl);
connection = (HttpURLConnection) realUrl.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setReadTimeout(5 * 1000);
connection.setConnectTimeout(3 * 1000);
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
connection.setRequestProperty("Accept-Charset", "application/json;charset=UTF-8");
//发送请求
connection.connect();
//获取请求返回的状态吗
int statusCode = connection.getResponseCode();
if (statusCode != 200){
//请求失败抛出异常
throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid.");
}
//如果返回值正常,数据在网络中是以流的形式得到服务端返回的数据
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
// 从流中读取响应信息
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
String responseMsg = stringBuilder.toString();
if(StringUtils.isNotEmpty(stringBuilder)) {
boolean json = JSONUtil.isJson(String.valueOf(stringBuilder));
if (json) {
JSON parse = JSONUtil.parse(stringBuilder);
boolean res = Boolean.parseBoolean(parse.getByPath("res").toString());
//发送成功,删除定时任务
if (res) {
String key = context.getJobDetail().getKey().toString();
String[] keySplit = key.split("\\.");
jobService.remove(keySplit[1], keySplit[0]);
}
}else{
String key = context.getJobDetail().getKey().toString();
String[] keySplit = key.split("\\.");
jobService.remove(keySplit[1], keySplit[0]);
}
}
log.info(responseMsg);
} catch (Exception e) {
log.error(e.getMessage());
} finally {
//关闭流与请求连接
try {
if (Objects.nonNull(bufferedReader)){
bufferedReader.close();
}
if (Objects.nonNull(connection)){
connection.disconnect();
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
}
@DisallowConcurrentExecution
的作用:
Quartz定时任务默认是并发执行的,不会等待上一次任务执行完毕,只要有间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。
@DisallowConcurrentExecution
这个注解是加在Job类上的,是禁止并发执行多个相同定义的JobDetail, , 但并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail。
创建JsonUtil类,用于将任务描述进行转化添加到Scheduler中
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.io.StringWriter;
/**
* @Author majinzhong
* @Date 2024/5/9 15:49
* @Version 1.0
*/
public class JsonUtils {
public static final ObjectMapper OBJECT_MAPPER = createObjectMapper();
public static ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
public static String object2Json(Object o) {
StringWriter sw = new StringWriter();
JsonGenerator gen = null;
try {
gen = new JsonFactory().createGenerator(sw);
OBJECT_MAPPER.writeValue(gen, o);
} catch (IOException e) {
throw new RuntimeException("Cannot serialize object as JSON", e);
} finally {
if (null != gen) {
try {
gen.close();
} catch (IOException e) {
throw new RuntimeException("Cannot serialize object as JSON", e);
}
}
}
return sw.toString();
}
}
JobService
import com.dreampen.dto.JobInfo;
import org.springframework.web.bind.annotation.RequestBody;
/**
* @Author majinzhong
* @Date 2024/5/9 15:55
* @Version 1.0
*/
public interface JobService {
/**
* 新建一个定时任务
* @param jobInfo 任务信息
* @return 任务信息
*/
JobInfo save(@RequestBody JobInfo jobInfo);
/**
* 新建一个简单定时任务
* @param jobInfo 任务信息
* @return 任务信息
*/
JobInfo simpleSave(@RequestBody JobInfo jobInfo);
/**
* 删除任务
* @param jobName 任务名称
* @param jobGroup 任务组
*/
void remove( String jobName,String jobGroup);
/**
* 恢复任务
* @param jobName 任务名称
* @param jobGroup 任务组
*/
void resume(String jobName, String jobGroup);
/**
* 暂停任务
* @param jobName 任务名称
* @param jobGroup 任务组
*/
void pause(String jobName, String jobGroup);
/**
* 立即执行任务一主要是用于执行一次任务的场景
* @param jobName 任务名称
* @param jobGroup 任务组
*/
void trigger(String jobName, String jobGroup);
}
JobServiceImpl
import com.dreampen.dto.JobInfo;
import com.dreampen.service.JobService;
import com.dreampen.util.HttpRemoteJob;
import com.dreampen.util.JsonUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
import java.util.TimeZone;
/**
* @Author majinzhong
* @Date 2024/5/9 15:56
* @Version 1.0
*/
@Service
public class JobServiceImpl implements JobService {
@Autowired
private Scheduler scheduler;
@Override
public JobInfo save(JobInfo jobInfo) {
//查询是否已有相同任务 jobKey可以唯一确定一个任务
JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
try {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (Objects.nonNull(jobDetail)){
scheduler.deleteJob(jobKey);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
//任务详情
JobDetail jobDetail = JobBuilder.newJob(HttpRemoteJob.class)
.withDescription(JsonUtils.object2Json(jobInfo.getJsonParams())) //任务描述
.withIdentity(jobKey) //指定任务
.build();
//根据cron,TimeZone时区,指定执行计划
CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule(jobInfo.getCron())
.inTimeZone(TimeZone.getTimeZone(jobInfo.getTimeZoneId()));
//触发器
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup()).startNow()
.withSchedule(builder)
.build();
//添加任务
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
System.out.println(e.getMessage());
}
return jobInfo;
}
@Override
public JobInfo simpleSave(JobInfo jobInfo) {
JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup()); //作业名称及其组名
//判断是否有相同的作业
try {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if(jobDetail != null){
scheduler.deleteJob(jobKey);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
//定义作业的详细信息,并设置要执行的作业类名,设置作业名称及其组名
JobDetail jobDetail = JobBuilder.newJob(HttpRemoteJob.class)
.withDescription(JsonUtils.object2Json(jobInfo.getJsonParams()))
.withIdentity(jobKey)
.build()
;
//简单触发器,着重与时间间隔
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
.startAt(jobInfo.getTriggerTime())
.build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
System.out.println(e.getMessage());
}
return jobInfo;
}
@Override
public void remove(String jobName, String jobGroup) {
//获取任务触发器
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
try {
//停止触发器
scheduler.pauseTrigger(triggerKey);
//移除触发器
scheduler.unscheduleJob(triggerKey);
//删除任务
scheduler.deleteJob(JobKey.jobKey(jobName,jobGroup));
} catch (SchedulerException e) {
System.out.println(e.getMessage());
}
}
@Override
public void resume(String jobName, String jobGroup) {
try {
//根据jobName,jobGroup获取jobKey 恢复任务
scheduler.resumeJob(JobKey.jobKey(jobName,jobGroup));
} catch (SchedulerException e) {
System.out.println(e.getMessage());
}
}
@Override
public void pause(String jobName, String jobGroup) {
try {
//根据jobName,jobGroup获取jobKey 暂停任务
scheduler.pauseJob(JobKey.jobKey(jobName,jobGroup));
} catch (SchedulerException e) {
System.out.println(e.getMessage());
}
}
@Override
public void trigger(String jobName, String jobGroup) {
try {
//根据jobName,jobGroup获取jobKey 立即执行任务
scheduler.triggerJob(JobKey.jobKey(jobName,jobGroup));
} catch (SchedulerException e) {
System.out.println(e.getMessage());
}
}
}
QuartzController,进行测试
import com.dreampen.dto.JobInfo;
import com.dreampen.service.JobService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author majinzhong
* @Date 2024/5/9 15:58
* @Version 1.0
*/
@RestController
@RequestMapping("/quartz/job")
public class QuartzController {
private final JobService jobService;
public QuartzController(JobService jobService) {
this.jobService = jobService;
}
@GetMapping("/test")
public void test(){
JobInfo jobInfo = new JobInfo();
jobInfo.setJobName("test-job");
jobInfo.setJobGroup("test");
jobInfo.setTimeZoneId("Asia/Shanghai"); //时区指定上海
jobInfo.setCron("0/5 * * * * ? "); //每5秒执行一次
Map<String, Object> params = new HashMap<>();
//添加需要调用的接口信息
String ss="test123";
String callUrl = "http://127.0.0.1:8085/quartz/job/test/run?s="+ss;
params.put("callUrl", callUrl);
jobInfo.setJsonParams(params);
jobService.save(jobInfo);
}
@GetMapping("/test/run")
public String runTest(String s){
System.out.println("打印入参:"+s);
System.out.println(new Date());
return "success";
}
@GetMapping("/test/delete")
public void deleteTest(String jobName,String jobGroup){
jobService.remove(jobName,jobGroup);
System.out.println("任务已删除");
}
}
测试结果
因为在HttpRemoteJob类中添加了如果成功就移除任务的逻辑,所以数据库中不会有任务数据,只有在失败的时候,数据库中才会有任务数据