MT:给magic-api动态添加定时任务

This commit is contained in:
MT 2021-11-23 19:53:50 +08:00
parent cecdf7b3a9
commit a0590ada4e
10 changed files with 649 additions and 3 deletions

View File

@ -0,0 +1,28 @@
<template>
<el-table :data="tableData" stripe border style="width: 100%">
<el-table-column prop="date" label="日期" width="180"></el-table-column>
<el-table-column prop="name" label="姓名" width="180"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<el-table-column fixed="right" label="操作" width="100">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
name: "index",
methods: {
handleClick(row) {
console.log(row);
}
},
}
</script>
<style scoped>
</style>

View File

@ -56,6 +56,15 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId> <artifactId>spring-boot-starter-quartz</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,54 @@
package org.ssssssss.magicboot.form;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
/**
* 新增定时任务
*/
@Getter
@Setter
public class AddJobForm {
/**
* 任务名称
*/
private String jName;
/**
* 任务组
*/
private String jGroup;
/**
* 触发器名称
*/
private String tName;
/**
* 触发器组
*/
private String tGroup;
/**
* cron表达式
*/
private String cron;
/**
* 执行MagicAPI中的接口,原始内容不包含code以及message信息
* Params:
* method 请求方法
*/
private String method;
/**
* 执行MagicAPI中的接口,原始内容不包含code以及message信息
* Params:
* path 请求路径
*/
private String path;
/**
* 执行MagicAPI中的接口,原始内容不包含code以及message信息
* Params:
* context 变量信息
*/
private Map<String,Object> context;
}

View File

@ -0,0 +1,62 @@
package org.ssssssss.magicboot.quartz;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.provider.MagicAPIService;
import java.util.Date;
import java.util.HashMap;
import java.util.Optional;
/**
* 基于magic-api接口的定时任务
*/
@Slf4j
@Component
public class MagicApiJob extends QuartzJobBean {
@Autowired
private MagicAPIService magicAPIService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
/**
* 这是一个接口任务
* 需要执行magic-api接口的代码
* 首先你需要配置好magic-api接口得到接口的请求方式请求地址请求参数
* 然后这个job会调用在java层调用magic-api的java代码去执行
* 这样一个完成的基于magic-api的定时任务接口就完成了
*/
// 获取之前保存的参数
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
// 取出请求方式与路径
String path = jobDataMap.getString("path");
String method = jobDataMap.getString("method");
Optional.ofNullable(path).orElseThrow(()->new RuntimeException("path 不能为空"));
Optional.ofNullable(method).orElseThrow(()->new RuntimeException("method 不能为空"));
// 移除请求方式与路径剩下的都是参数
jobDataMap.remove("path");
jobDataMap.remove("method");
/**
*
* 执行MagicAPI中的接口,原始内容不包含code以及message信息
* Params:
* method 请求方法
* path 请求路径
* context 变量信息
*/
log.info("开始执行magicApi定时任务");
magicAPIService.execute(method,path,jobDataMap);
log.info("结束执行magicApi定时任务");
}
}

View File

@ -0,0 +1,78 @@
package org.ssssssss.magicboot.quartz;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.ssssssss.magicboot.form.AddJobForm;
import org.ssssssss.magicboot.vo.Result;
/**
* 定时任务控制器
*/
@Slf4j
@Controller
@RequestMapping("/job")
public class ScheduledTasksController {
@Autowired
private ScheduledTasksService scheduledTasksService;
/**
* 获取所有运行中的任务
* @return
*/
@ResponseBody
@RequestMapping("/getAllJob")
public Result getAllJob() {
return scheduledTasksService.getAllJob();
}
/**
* 新增一个定时任务
* @param form
* @return
*/
@ResponseBody
@RequestMapping("/addJob")
public Result addJob(AddJobForm form) {
scheduledTasksService.addJob(form);
return Result.isSuccess("添加定时任务 成功");
}
/**
* 暂停定时任务
* @param jName 任务名
* @param jGroup 任务组
*/
@ResponseBody
@RequestMapping("/pauseJob")
public Result pauseJob(String jName, String jGroup) {
scheduledTasksService.pauseJob(jName, jGroup);
return Result.isSuccess("暂停定时任务 成功");
}
/**
* 继续定时任务
* @param jName 任务名
* @param jGroup 任务组
*/
@ResponseBody
@RequestMapping("/resumeJob")
public Result resumeJob(String jName, String jGroup) {
scheduledTasksService.resumeJob(jName, jGroup);
return Result.isSuccess("继续定时任务 成功");
}
/**
* 删除定时任务
* @param jName 任务名
* @param jGroup 任务组
*/
@ResponseBody
@RequestMapping("/resumeJob")
public Result deleteJob(String jName, String jGroup) {
scheduledTasksService.deleteJob(jName, jGroup);
return Result.isSuccess("删除定时任务 成功");
}
}

View File

@ -0,0 +1,135 @@
package org.ssssssss.magicboot.quartz;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.ssssssss.magicboot.form.AddJobForm;
import org.ssssssss.magicboot.vo.Result;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* 定时任务业务控制层
*/
@Service
public class ScheduledTasksService {
@Autowired
private Scheduler scheduler;
/**
* 获取所有运行中的任务
* @return
*/
public Result getAllJob(){
try {
List<AddJobForm> formList = new ArrayList<>();
AddJobForm form = null;
for (TriggerKey triggerKey : scheduler.getTriggerKeys(GroupMatcher.anyGroup())) {
///通过triggerKey在scheduler中获取trigger对象
CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);
JobDetail jobDetail = scheduler.getJobDetail(trigger.getJobKey());
form = new AddJobForm();
form.setMethod(jobDetail.getJobDataMap().getString("method"));
form.setPath(jobDetail.getJobDataMap().getString("path"));
jobDetail.getJobDataMap().remove("method");
jobDetail.getJobDataMap().remove("path");
form.setContext(jobDetail.getJobDataMap());
form.setJName(jobDetail.getKey().getName());
form.setJGroup(jobDetail.getKey().getGroup());
form.setTName(trigger.getJobKey().getName());
form.setTGroup(trigger.getJobKey().getGroup());
formList.add(form);
}
return Result.isSuccess(form);
} catch (SchedulerException e) {
e.printStackTrace();
return Result.isBad("获取所有任务失败:{}",e.getMessage());
}
}
/**
* 新增一个定时任务
*/
public void addJob(AddJobForm form) {
Optional.ofNullable(form).orElseThrow(()->new RuntimeException("参数 不能为空"));
Optional.ofNullable(form.getPath()).orElseThrow(()->new RuntimeException("path 不能为空"));
Optional.ofNullable(form.getMethod()).orElseThrow(()->new RuntimeException("method 不能为空"));
Optional.ofNullable(form.getJName()).orElseThrow(()->new RuntimeException("任务名称 不能为空"));
Optional.ofNullable(form.getTName()).orElseThrow(()->new RuntimeException("触发器名称 不能为空"));
Optional.ofNullable(form.getCron()).orElseThrow(()->new RuntimeException("cron表达式 不能为空"));
try {
// 携带参数供执行job时调用
JobDataMap newJobDataMap = new JobDataMap();
newJobDataMap.put("method",form.getMethod());
newJobDataMap.put("path",form.getPath());
newJobDataMap.putAll(form.getContext());
JobDetail jobDetail = JobBuilder.newJob(MagicApiJob.class)
.withIdentity(form.getJName(), form.getJGroup())
.setJobData(newJobDataMap)
.build();
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(form.getTName(), form.getTGroup())
.usingJobData(newJobDataMap)
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(form.getCron()))
.build();
scheduler.start();
scheduler.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 暂停定时任务
* @param jName 任务名
* @param jGroup 任务组
*/
public void pauseJob(String jName, String jGroup) {
try {
scheduler.pauseJob(JobKey.jobKey(jName, jGroup));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 继续定时任务
* @param jName 任务名
* @param jGroup 任务组
*/
public void resumeJob(String jName, String jGroup) {
try {
scheduler.resumeJob(JobKey.jobKey(jName, jGroup));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 删除定时任务
* @param jName 任务名
* @param jGroup 任务组
*/
public void deleteJob(String jName, String jGroup) {
try {
scheduler.deleteJob(JobKey.jobKey(jName, jGroup));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,112 @@
package org.ssssssss.magicboot.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Result<T> {
// 错误码
private String code;
// 提示信息
private String msg;
// 具体的内容
private T data;
// 是否成功
private boolean success;
// 总数
private Long total;
public Result() {
}
public Result(String code, String msg, T data, boolean success) {
this.code = code;
this.msg = msg;
this.data = data;
this.success = success;
}
public static<T> Result<T> isSuccess(T data) {
Result<T> objectResult = new Result<T>();
objectResult.setCode("200");
objectResult.setSuccess(true);
objectResult.setMsg("成功");
objectResult.setData(data);
return objectResult;
}
public static<T> Result<T> isSuccess(T data, Long count) {
Result<T> objectResult = new Result<T>();
objectResult.setCode("200");
objectResult.setSuccess(true);
objectResult.setMsg("成功");
objectResult.setData(data);
objectResult.setTotal(count);
return objectResult;
}
public static<T> Result<T> isBad(T data) {
Result<T> objectResult = new Result<T>();
objectResult.setCode("400");
objectResult.setSuccess(false);
objectResult.setMsg("失败");
objectResult.setData(data);
return objectResult;
}
public static<T> Result<T> isBad(String msg) {
Result<T> objectResult = new Result<>();
objectResult.setCode("400");
objectResult.setSuccess(false);
objectResult.setMsg(msg);
return objectResult;
}
public static<T> Result<T> isBad(String msg, String code) {
Result<T> objectResult = new Result<T>();
objectResult.setCode(code);
objectResult.setSuccess(false);
objectResult.setMsg(msg);
return objectResult;
}
public static<T> Result<T> getResult(boolean isSuccess, T data) {
if (isSuccess) {
return Result.isSuccess(data);
}
return Result.isBad(data);
}
public static<T> Result<T> getResult(boolean isSuccess, T data, String msg) {
if (isSuccess) {
return Result.isSuccess(data);
}
return Result.isBad(msg);
}
public static<T> Result<T> getResult(boolean isSuccess, String msg) {
if (isSuccess) {
return Result.isSuccess(null);
}
return Result.isBad(msg);
}
public static<T> Result<T> getResult(boolean isSuccess, String msg, String code) {
if (isSuccess) {
return Result.isSuccess(null);
}
return Result.isBad(msg, code);
}
@Override
public String toString() {
return "Result{" +
"code='" + code + '\'' +
", msg='" + msg + '\'' +
", data=" + data +
", success=" + success +
'}';
}
}

View File

@ -0,0 +1,6 @@
spring:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
schema: classpath:schema/tables_mysql.sql

View File

@ -7,6 +7,9 @@ server:
spring: spring:
profiles: profiles:
active: dev active: dev
include:
- online
- quartz
servlet: servlet:
multipart: multipart:
max-file-size: 200MB max-file-size: 200MB
@ -15,9 +18,9 @@ spring:
date-format: yyyy-MM-dd HH:mm:ss date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8 time-zone: GMT+8
datasource: datasource:
url: jdbc:mysql://localhost:3307/magic-boot?useSSL=false&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai url: jdbc:mysql://localhost:3306/magic-boot?useSSL=false&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai
username: root username: root
password: root password: "********"
upload: upload:
# oss,disk磁盘 # oss,disk磁盘
@ -68,4 +71,4 @@ sa-token:
# token风格 # token风格
token-style: uuid token-style: uuid
# 是否输出操作日志 # 是否输出操作日志
is-log: false is-log: false

View File

@ -0,0 +1,159 @@
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
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)
);
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)
);
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)
);
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)
);
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)
);
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)
);
commit;