新增定时任务
This commit is contained in:
parent
7587a053c4
commit
b241dd45cd
|
|
@ -1,5 +1,6 @@
|
|||
## 项目说明
|
||||
- FastBoot是采用SpringBoot、SpringSecurity、Mybatis-Plus等框架,开发的一套SpringBoot快速开发系统,使用门槛极低,且采用MIT开源协议,完全免费开源,可免费用于**商业项目**等场景。
|
||||
- 采用组件模式,扩展不同的业务功能,可以很方便的实现各种业务需求,且不会导致系统臃肿,若想使用某个组件,按需引入即可,反之亦然。
|
||||
- 开发文档:[https://maku.net/docs/fast-boot](https://maku.net/docs/fast-boot)
|
||||
- 演示环境:https://demo.maku.net/fast-boot
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,216 @@
|
|||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (1, '定时任务', 'quartz/schedule/index', NULL, 0, 0, 'icon-reloadtime', 0, 0, 0, 10000, now(), 10000, now());
|
||||
|
||||
SET @menuId = @@identity;
|
||||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @menuId), '查看', '', 'schedule:page', 1, 0, '', 0, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @menuId), '新增', '', 'schedule:save', 1, 0, '', 1, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @menuId), '修改', '', 'schedule:update,schedule:info', 1, 0, '', 2, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @menuId), '删除', '', 'schedule:delete', 1, 0, '', 3, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @menuId), '立即运行', '', 'schedule:run', 1, 0, '', 2, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_menu (pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @menuId), '日志', '', 'schedule:log', 1, 0, '', 4, 0, 0, 10000, now(), 10000, now());
|
||||
|
||||
INSERT INTO sys_dict_type (dict_type, dict_name, remark, sort, version, deleted, creator, create_time, updater, update_time) VALUES ('schedule_group', '定时任务', '任务组名', 0, 0, 0, 10000, now(), 10000, now());
|
||||
|
||||
SET @typeId = @@identity;
|
||||
INSERT INTO sys_dict_data (dict_type_id, dict_label, dict_value, remark, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @typeId), '默认', 'default', '', 0, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_dict_data (dict_type_id, dict_label, dict_value, remark, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @typeId), '系统', 'system', '', 1, 0, 0, 10000, now(), 10000, now());
|
||||
|
||||
INSERT INTO sys_dict_type (dict_type, dict_name, remark, sort, version, deleted, creator, create_time, updater, update_time) VALUES ('schedule_status', '定时任务', '状态', 0, 0, 0, 10000, now(), 10000, now());
|
||||
|
||||
SET @typeId = @@identity;
|
||||
INSERT INTO sys_dict_data (dict_type_id, dict_label, dict_value, remark, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @typeId), '暂停', '0', '', 0, 0, 0, 10000, now(), 10000, now());
|
||||
INSERT INTO sys_dict_data (dict_type_id, dict_label, dict_value, remark, sort, version, deleted, creator, create_time, updater, update_time) VALUES ((SELECT @typeId), '正常', '1', '', 1, 0, 0, 10000, now(), 10000, now());
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS schedule_job;
|
||||
DROP TABLE IF EXISTS schedule_job_log;
|
||||
|
||||
CREATE TABLE schedule_job (
|
||||
id bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
job_name varchar(200) COMMENT '名称',
|
||||
job_group varchar(100) COMMENT '分组',
|
||||
bean_name varchar(200) COMMENT 'spring bean名称',
|
||||
method varchar(100) COMMENT '执行方法',
|
||||
params varchar(2000) COMMENT '参数',
|
||||
cron_expression varchar(100) COMMENT 'cron表达式',
|
||||
status tinyint unsigned COMMENT '状态 0:暂停 1:正常',
|
||||
concurrent tinyint unsigned COMMENT '是否并发 0:禁止 1:允许',
|
||||
remark varchar(255) COMMENT '备注',
|
||||
version int COMMENT '版本号',
|
||||
deleted tinyint COMMENT '删除标识 0:正常 1:已删除',
|
||||
creator bigint COMMENT '创建者',
|
||||
create_time datetime COMMENT '创建时间',
|
||||
updater bigint COMMENT '更新者',
|
||||
update_time datetime COMMENT '更新时间',
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='定时任务';
|
||||
|
||||
CREATE TABLE schedule_job_log (
|
||||
id bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
job_id bigint NOT NULL COMMENT '任务id',
|
||||
job_name varchar(200) COMMENT '任务名称',
|
||||
job_group varchar(100) COMMENT '任务组名',
|
||||
bean_name varchar(200) COMMENT 'spring bean名称',
|
||||
method varchar(100) COMMENT '执行方法',
|
||||
params varchar(2000) COMMENT '参数',
|
||||
status tinyint unsigned NOT NULL COMMENT '任务状态 0:失败 1:成功',
|
||||
error varchar(2000) COMMENT '异常信息',
|
||||
times bigint NOT NULL COMMENT '耗时(单位:毫秒)',
|
||||
create_time datetime COMMENT '创建时间',
|
||||
PRIMARY KEY (id),
|
||||
key idx_job_id (job_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='定时任务日志';
|
||||
|
||||
|
||||
INSERT INTO schedule_job (id, job_name, job_group, bean_name, method, params, cron_expression, status, concurrent, remark, version, deleted, creator, create_time, updater, update_time) VALUES (1, '测试任务', 'system', 'testTask', 'run', '123', '0 * * * * ? *', 0, 0, '', 14, 0, 10000, now(), 10000, now());
|
||||
|
||||
|
||||
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- 以下为Quartz框架,自带的表结构
|
||||
-- ----------------------------------------------------------
|
||||
|
||||
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 comment '调度名称',
|
||||
job_name varchar(200) not null comment '任务名称',
|
||||
job_group varchar(200) not null comment '任务组名',
|
||||
description varchar(250) null comment '相关介绍',
|
||||
job_class_name varchar(250) not null comment '执行任务类名称',
|
||||
is_durable varchar(1) not null comment '是否持久化',
|
||||
is_nonconcurrent varchar(1) not null comment '是否并发',
|
||||
is_update_data varchar(1) not null comment '是否更新数据',
|
||||
requests_recovery varchar(1) not null comment '是否接受恢复执行',
|
||||
job_data blob null comment '存放持久化job对象',
|
||||
primary key (sched_name, job_name, job_group)
|
||||
) ENGINE=InnoDB COMMENT = '任务详细信息表';
|
||||
|
||||
create table QRTZ_TRIGGERS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
trigger_name varchar(200) not null comment '触发器的名字',
|
||||
trigger_group varchar(200) not null comment '触发器所属组的名字',
|
||||
job_name varchar(200) not null comment 'qrtz_job_details表job_name的外键',
|
||||
job_group varchar(200) not null comment 'qrtz_job_details表job_group的外键',
|
||||
description varchar(250) null comment '相关介绍',
|
||||
next_fire_time bigint(13) null comment '上一次触发时间(毫秒)',
|
||||
prev_fire_time bigint(13) null comment '下一次触发时间(默认为-1表示不触发)',
|
||||
priority integer null comment '优先级',
|
||||
trigger_state varchar(16) not null comment '触发器状态',
|
||||
trigger_type varchar(8) not null comment '触发器的类型',
|
||||
start_time bigint(13) not null comment '开始时间',
|
||||
end_time bigint(13) null comment '结束时间',
|
||||
calendar_name varchar(200) null comment '日程表名称',
|
||||
misfire_instr smallint(2) null comment '补偿执行的策略',
|
||||
job_data blob null comment '存放持久化job对象',
|
||||
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)
|
||||
) ENGINE=InnoDB COMMENT = '触发器详细信息表';
|
||||
|
||||
create table QRTZ_SIMPLE_TRIGGERS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
|
||||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
|
||||
repeat_count bigint(7) not null comment '重复的次数统计',
|
||||
repeat_interval bigint(12) not null comment '重复的间隔时间',
|
||||
times_triggered bigint(10) not null comment '已经触发的次数',
|
||||
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)
|
||||
) ENGINE=InnoDB COMMENT = '简单触发器的信息表';
|
||||
|
||||
create table QRTZ_CRON_TRIGGERS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
|
||||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
|
||||
cron_expression varchar(200) not null comment 'cron表达式',
|
||||
time_zone_id varchar(80) comment '时区',
|
||||
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)
|
||||
) ENGINE=InnoDB COMMENT = 'Cron类型的触发器表';
|
||||
|
||||
create table QRTZ_BLOB_TRIGGERS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
|
||||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
|
||||
blob_data blob null comment '存放持久化Trigger对象',
|
||||
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)
|
||||
) ENGINE=InnoDB COMMENT = 'Blob类型的触发器表';
|
||||
|
||||
create table QRTZ_CALENDARS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
calendar_name varchar(200) not null comment '日历名称',
|
||||
calendar blob not null comment '存放持久化calendar对象',
|
||||
primary key (sched_name, calendar_name)
|
||||
) ENGINE=InnoDB COMMENT = '日历信息表';
|
||||
|
||||
create table QRTZ_PAUSED_TRIGGER_GRPS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
|
||||
primary key (sched_name, trigger_group)
|
||||
) ENGINE=InnoDB COMMENT = '暂停的触发器表';
|
||||
|
||||
create table QRTZ_FIRED_TRIGGERS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
entry_id varchar(95) not null comment '调度器实例id',
|
||||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
|
||||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
|
||||
instance_name varchar(200) not null comment '调度器实例名',
|
||||
fired_time bigint(13) not null comment '触发的时间',
|
||||
sched_time bigint(13) not null comment '定时器制定的时间',
|
||||
priority integer not null comment '优先级',
|
||||
state varchar(16) not null comment '状态',
|
||||
job_name varchar(200) null comment '任务名称',
|
||||
job_group varchar(200) null comment '任务组名',
|
||||
is_nonconcurrent varchar(1) null comment '是否并发',
|
||||
requests_recovery varchar(1) null comment '是否接受恢复执行',
|
||||
primary key (sched_name, entry_id)
|
||||
) ENGINE=InnoDB COMMENT = '已触发的触发器表';
|
||||
|
||||
create table QRTZ_SCHEDULER_STATE (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
instance_name varchar(200) not null comment '实例名称',
|
||||
last_checkin_time bigint(13) not null comment '上次检查时间',
|
||||
checkin_interval bigint(13) not null comment '检查间隔时间',
|
||||
primary key (sched_name, instance_name)
|
||||
) ENGINE=InnoDB COMMENT = '调度器状态表';
|
||||
|
||||
create table QRTZ_LOCKS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
lock_name varchar(40) not null comment '悲观锁名称',
|
||||
primary key (sched_name, lock_name)
|
||||
) ENGINE=InnoDB COMMENT = '存储的悲观锁信息表';
|
||||
|
||||
create table QRTZ_SIMPROP_TRIGGERS (
|
||||
sched_name varchar(120) not null comment '调度名称',
|
||||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键',
|
||||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键',
|
||||
str_prop_1 varchar(512) null comment 'String类型的trigger的第一个参数',
|
||||
str_prop_2 varchar(512) null comment 'String类型的trigger的第二个参数',
|
||||
str_prop_3 varchar(512) null comment 'String类型的trigger的第三个参数',
|
||||
int_prop_1 int null comment 'int类型的trigger的第一个参数',
|
||||
int_prop_2 int null comment 'int类型的trigger的第二个参数',
|
||||
long_prop_1 bigint null comment 'long类型的trigger的第一个参数',
|
||||
long_prop_2 bigint null comment 'long类型的trigger的第二个参数',
|
||||
dec_prop_1 numeric(13,4) null comment 'decimal类型的trigger的第一个参数',
|
||||
dec_prop_2 numeric(13,4) null comment 'decimal类型的trigger的第二个参数',
|
||||
bool_prop_1 varchar(1) null comment 'Boolean类型的trigger的第一个参数',
|
||||
bool_prop_2 varchar(1) null comment 'Boolean类型的trigger的第二个参数',
|
||||
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)
|
||||
) ENGINE=InnoDB COMMENT = '同步机制的行锁表';
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
## 说明
|
||||
fast-boot 是采用组件模式,扩展不同的业务功能,可以很方便的实现各种业务需求,且不会导致系统臃肿,若想使用某个组件,按需引入即可,反之亦然。
|
||||
|
||||
## 引入
|
||||
如果需要使用对应的组件,如:`fast-boot-quartz`,则需要在`fast-boot/fast-server/pom.xml`里面引入,如下所示:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>net.maku</groupId>
|
||||
<artifactId>fast-boot-quartz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## SQL语句
|
||||
引入组件时,还需要执行对应的SQL文件,初始化表结构和菜单等。
|
||||
如果使用的是MySQL数据库,则需要执行以下SQL文件:
|
||||
|
||||
```
|
||||
fast-boot/db/mysql/module/fast-boot-quartz.sql
|
||||
```
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>net.maku</groupId>
|
||||
<artifactId>fast-boot-module</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>fast-boot-quartz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.maku</groupId>
|
||||
<artifactId>fast-framework</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package net.maku.quartz.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.maku.framework.common.page.PageResult;
|
||||
import net.maku.framework.common.utils.Result;
|
||||
import net.maku.quartz.convert.ScheduleJobConvert;
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import net.maku.quartz.query.ScheduleJobQuery;
|
||||
import net.maku.quartz.service.ScheduleJobService;
|
||||
import net.maku.quartz.utils.CronUtils;
|
||||
import net.maku.quartz.vo.ScheduleJobVO;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("schedule")
|
||||
@Tag(name="定时任务")
|
||||
@AllArgsConstructor
|
||||
public class ScheduleJobController {
|
||||
private final ScheduleJobService scheduleJobService;
|
||||
|
||||
@GetMapping("page")
|
||||
@Operation(summary = "分页")
|
||||
@PreAuthorize("hasAuthority('schedule:page')")
|
||||
public Result<PageResult<ScheduleJobVO>> page(@Valid ScheduleJobQuery query){
|
||||
PageResult<ScheduleJobVO> page = scheduleJobService.page(query);
|
||||
|
||||
return Result.ok(page);
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
@Operation(summary = "信息")
|
||||
@PreAuthorize("hasAuthority('schedule:info')")
|
||||
public Result<ScheduleJobVO> get(@PathVariable("id") Long id){
|
||||
ScheduleJobEntity entity = scheduleJobService.getById(id);
|
||||
|
||||
return Result.ok(ScheduleJobConvert.INSTANCE.convert(entity));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "保存")
|
||||
@PreAuthorize("hasAuthority('schedule:save')")
|
||||
public Result<String> save(@RequestBody ScheduleJobVO vo){
|
||||
if (!CronUtils.isValid(vo.getCronExpression())) {
|
||||
return Result.error("操作失败,Cron表达式不正确");
|
||||
}
|
||||
|
||||
scheduleJobService.save(vo);
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Operation(summary = "修改")
|
||||
@PreAuthorize("hasAuthority('schedule:update')")
|
||||
public Result<String> update(@RequestBody @Valid ScheduleJobVO vo) {
|
||||
if (!CronUtils.isValid(vo.getCronExpression())) {
|
||||
return Result.error("操作失败,Cron表达式不正确");
|
||||
}
|
||||
|
||||
scheduleJobService.update(vo);
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@Operation(summary = "删除")
|
||||
@PreAuthorize("hasAuthority('schedule:delete')")
|
||||
public Result<String> delete(@RequestBody List<Long> idList){
|
||||
scheduleJobService.delete(idList);
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@PutMapping("run")
|
||||
@Operation(summary = "立即执行")
|
||||
@PreAuthorize("hasAuthority('schedule:run')")
|
||||
public Result<String> run(@RequestBody ScheduleJobVO vo){
|
||||
scheduleJobService.run(vo);
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@PutMapping("change-status")
|
||||
@Operation(summary = "修改状态")
|
||||
@PreAuthorize("hasAuthority('schedule:update')")
|
||||
public Result<String> changeStatus(@RequestBody ScheduleJobVO vo){
|
||||
scheduleJobService.changeStatus(vo);
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package net.maku.quartz.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.maku.framework.common.page.PageResult;
|
||||
import net.maku.framework.common.utils.Result;
|
||||
import net.maku.quartz.convert.ScheduleJobLogConvert;
|
||||
import net.maku.quartz.entity.ScheduleJobLogEntity;
|
||||
import net.maku.quartz.query.ScheduleJobLogQuery;
|
||||
import net.maku.quartz.service.ScheduleJobLogService;
|
||||
import net.maku.quartz.vo.ScheduleJobLogVO;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("schedule/log")
|
||||
@Tag(name="定时任务日志")
|
||||
@AllArgsConstructor
|
||||
public class ScheduleJobLogController {
|
||||
private final ScheduleJobLogService scheduleJobLogService;
|
||||
|
||||
@GetMapping("page")
|
||||
@Operation(summary = "分页")
|
||||
@PreAuthorize("hasAuthority('schedule:log')")
|
||||
public Result<PageResult<ScheduleJobLogVO>> page(@Valid ScheduleJobLogQuery query){
|
||||
PageResult<ScheduleJobLogVO> page = scheduleJobLogService.page(query);
|
||||
|
||||
return Result.ok(page);
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
@Operation(summary = "信息")
|
||||
@PreAuthorize("hasAuthority('schedule:log')")
|
||||
public Result<ScheduleJobLogVO> get(@PathVariable("id") Long id){
|
||||
ScheduleJobLogEntity entity = scheduleJobLogService.getById(id);
|
||||
|
||||
return Result.ok(ScheduleJobLogConvert.INSTANCE.convert(entity));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package net.maku.quartz.convert;
|
||||
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import net.maku.quartz.vo.ScheduleJobVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface ScheduleJobConvert {
|
||||
ScheduleJobConvert INSTANCE = Mappers.getMapper(ScheduleJobConvert.class);
|
||||
|
||||
ScheduleJobEntity convert(ScheduleJobVO vo);
|
||||
|
||||
ScheduleJobVO convert(ScheduleJobEntity entity);
|
||||
|
||||
List<ScheduleJobVO> convertList(List<ScheduleJobEntity> list);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package net.maku.quartz.convert;
|
||||
|
||||
import net.maku.quartz.entity.ScheduleJobLogEntity;
|
||||
import net.maku.quartz.vo.ScheduleJobLogVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface ScheduleJobLogConvert {
|
||||
ScheduleJobLogConvert INSTANCE = Mappers.getMapper(ScheduleJobLogConvert.class);
|
||||
|
||||
ScheduleJobLogEntity convert(ScheduleJobLogVO vo);
|
||||
|
||||
ScheduleJobLogVO convert(ScheduleJobLogEntity entity);
|
||||
|
||||
List<ScheduleJobLogVO> convertList(List<ScheduleJobLogEntity> list);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package net.maku.quartz.dao;
|
||||
|
||||
import net.maku.framework.common.dao.BaseDao;
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface ScheduleJobDao extends BaseDao<ScheduleJobEntity> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package net.maku.quartz.dao;
|
||||
|
||||
import net.maku.framework.common.dao.BaseDao;
|
||||
import net.maku.quartz.entity.ScheduleJobLogEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface ScheduleJobLogDao extends BaseDao<ScheduleJobLogEntity> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package net.maku.quartz.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.maku.framework.common.entity.BaseEntity;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@TableName("schedule_job")
|
||||
public class ScheduleJobEntity extends BaseEntity {
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 任务组名
|
||||
*/
|
||||
private String jobGroup;
|
||||
|
||||
/**
|
||||
* bean名称
|
||||
*/
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
*/
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* 方法参数
|
||||
*/
|
||||
private String params;
|
||||
|
||||
/**
|
||||
* cron表达式
|
||||
*/
|
||||
private String cronExpression;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 是否并发 0:禁止 1:允许
|
||||
*/
|
||||
private Integer concurrent;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package net.maku.quartz.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("schedule_job_log")
|
||||
public class ScheduleJobLogEntity {
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private Long jobId;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 任务组名
|
||||
*/
|
||||
private String jobGroup;
|
||||
|
||||
/**
|
||||
* spring bean名称
|
||||
*/
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
*/
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
private String params;
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String error;
|
||||
|
||||
/**
|
||||
* 耗时(单位:毫秒)
|
||||
*/
|
||||
private Long times;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package net.maku.quartz.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 定时任务并发枚举
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ScheduleConcurrentEnum {
|
||||
/**
|
||||
* 禁止
|
||||
*/
|
||||
NO(0),
|
||||
/**
|
||||
* 允许
|
||||
*/
|
||||
YES(1);
|
||||
|
||||
private final int value;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package net.maku.quartz.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 定时任务状态枚举
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ScheduleStatusEnum {
|
||||
/**
|
||||
* 暂停
|
||||
*/
|
||||
PAUSE(0),
|
||||
/**
|
||||
* 正常
|
||||
*/
|
||||
NORMAL(1);
|
||||
|
||||
private final int value;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package net.maku.quartz.query;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.maku.framework.common.query.Query;
|
||||
|
||||
/**
|
||||
* 定时任务日志查询
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description = "定时任务日志查询")
|
||||
public class ScheduleJobLogQuery extends Query {
|
||||
@Schema(description = "任务id")
|
||||
private Long jobId;
|
||||
|
||||
@Schema(description = "任务名称")
|
||||
private String jobName;
|
||||
|
||||
@Schema(description = "任务组名")
|
||||
private String jobGroup;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package net.maku.quartz.query;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.maku.framework.common.query.Query;
|
||||
|
||||
/**
|
||||
* 定时任务查询
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description = "定时任务查询")
|
||||
public class ScheduleJobQuery extends Query {
|
||||
@Schema(description = "任务名称")
|
||||
private String jobName;
|
||||
|
||||
@Schema(description = "任务组名")
|
||||
private String jobGroup;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package net.maku.quartz.service;
|
||||
|
||||
import net.maku.framework.common.page.PageResult;
|
||||
import net.maku.framework.common.service.BaseService;
|
||||
import net.maku.quartz.entity.ScheduleJobLogEntity;
|
||||
import net.maku.quartz.query.ScheduleJobLogQuery;
|
||||
import net.maku.quartz.vo.ScheduleJobLogVO;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
public interface ScheduleJobLogService extends BaseService<ScheduleJobLogEntity> {
|
||||
|
||||
PageResult<ScheduleJobLogVO> page(ScheduleJobLogQuery query);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package net.maku.quartz.service;
|
||||
|
||||
import net.maku.framework.common.page.PageResult;
|
||||
import net.maku.framework.common.service.BaseService;
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import net.maku.quartz.query.ScheduleJobQuery;
|
||||
import net.maku.quartz.vo.ScheduleJobVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
public interface ScheduleJobService extends BaseService<ScheduleJobEntity> {
|
||||
|
||||
PageResult<ScheduleJobVO> page(ScheduleJobQuery query);
|
||||
|
||||
void save(ScheduleJobVO vo);
|
||||
|
||||
void update(ScheduleJobVO vo);
|
||||
|
||||
void delete(List<Long> idList);
|
||||
|
||||
void run(ScheduleJobVO vo);
|
||||
|
||||
void changeStatus(ScheduleJobVO vo);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package net.maku.quartz.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.maku.framework.common.page.PageResult;
|
||||
import net.maku.framework.common.service.impl.BaseServiceImpl;
|
||||
import net.maku.quartz.convert.ScheduleJobLogConvert;
|
||||
import net.maku.quartz.dao.ScheduleJobLogDao;
|
||||
import net.maku.quartz.entity.ScheduleJobLogEntity;
|
||||
import net.maku.quartz.query.ScheduleJobLogQuery;
|
||||
import net.maku.quartz.service.ScheduleJobLogService;
|
||||
import net.maku.quartz.vo.ScheduleJobLogVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class ScheduleJobLogServiceImpl extends BaseServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
|
||||
|
||||
@Override
|
||||
public PageResult<ScheduleJobLogVO> page(ScheduleJobLogQuery query) {
|
||||
IPage<ScheduleJobLogEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));
|
||||
|
||||
return new PageResult<>(ScheduleJobLogConvert.INSTANCE.convertList(page.getRecords()), page.getTotal());
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ScheduleJobLogEntity> getWrapper(ScheduleJobLogQuery query){
|
||||
LambdaQueryWrapper<ScheduleJobLogEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.like(StrUtil.isNotBlank(query.getJobName()), ScheduleJobLogEntity::getJobName, query.getJobName());
|
||||
wrapper.like(StrUtil.isNotBlank(query.getJobGroup()), ScheduleJobLogEntity::getJobGroup, query.getJobGroup());
|
||||
wrapper.eq(query.getJobId() != null, ScheduleJobLogEntity::getJobId, query.getJobId());
|
||||
wrapper.orderByDesc(ScheduleJobLogEntity::getId);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package net.maku.quartz.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.maku.framework.common.page.PageResult;
|
||||
import net.maku.framework.common.service.impl.BaseServiceImpl;
|
||||
import net.maku.quartz.convert.ScheduleJobConvert;
|
||||
import net.maku.quartz.dao.ScheduleJobDao;
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import net.maku.quartz.enums.ScheduleStatusEnum;
|
||||
import net.maku.quartz.query.ScheduleJobQuery;
|
||||
import net.maku.quartz.service.ScheduleJobService;
|
||||
import net.maku.quartz.utils.ScheduleUtils;
|
||||
import net.maku.quartz.vo.ScheduleJobVO;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
|
||||
private final Scheduler scheduler;
|
||||
|
||||
/**
|
||||
* 启动项目时,初始化定时器
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() throws SchedulerException {
|
||||
scheduler.clear();
|
||||
List<ScheduleJobEntity> scheduleJobList = baseMapper.selectList(null);
|
||||
for (ScheduleJobEntity scheduleJob : scheduleJobList) {
|
||||
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ScheduleJobVO> page(ScheduleJobQuery query) {
|
||||
IPage<ScheduleJobEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));
|
||||
|
||||
return new PageResult<>(ScheduleJobConvert.INSTANCE.convertList(page.getRecords()), page.getTotal());
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ScheduleJobEntity> getWrapper(ScheduleJobQuery query){
|
||||
LambdaQueryWrapper<ScheduleJobEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.like(StrUtil.isNotBlank(query.getJobName()), ScheduleJobEntity::getJobName, query.getJobName());
|
||||
wrapper.like(StrUtil.isNotBlank(query.getJobGroup()), ScheduleJobEntity::getJobGroup, query.getJobGroup());
|
||||
wrapper.eq(query.getStatus() != null, ScheduleJobEntity::getStatus, query.getStatus());
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(ScheduleJobVO vo) {
|
||||
ScheduleJobEntity entity = ScheduleJobConvert.INSTANCE.convert(vo);
|
||||
|
||||
entity.setStatus(ScheduleStatusEnum.PAUSE.getValue());
|
||||
if(baseMapper.insert(entity) > 0) {
|
||||
ScheduleUtils.createScheduleJob(scheduler, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ScheduleJobVO vo) {
|
||||
ScheduleJobEntity entity = ScheduleJobConvert.INSTANCE.convert(vo);
|
||||
|
||||
// 更新定时任务
|
||||
if(updateById(entity)) {
|
||||
ScheduleJobEntity scheduleJob = getById(entity.getId());
|
||||
ScheduleUtils.updateSchedulerJob(scheduler, scheduleJob);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(List<Long> idList) {
|
||||
for(Long id: idList){
|
||||
ScheduleJobEntity scheduleJob = getById(id);
|
||||
|
||||
// 删除定时任务
|
||||
if (removeById(id)) {
|
||||
ScheduleUtils.deleteScheduleJob(scheduler, scheduleJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ScheduleJobVO vo) {
|
||||
ScheduleJobEntity scheduleJob = getById(vo.getId());
|
||||
if(scheduleJob == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScheduleUtils.run(scheduler, scheduleJob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeStatus(ScheduleJobVO vo) {
|
||||
ScheduleJobEntity scheduleJob = getById(vo.getId());
|
||||
if(scheduleJob == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新数据
|
||||
scheduleJob.setStatus(vo.getStatus());
|
||||
updateById(scheduleJob);
|
||||
|
||||
if(ScheduleStatusEnum.PAUSE.getValue() == vo.getStatus()) {
|
||||
ScheduleUtils.pauseJob(scheduler, scheduleJob);
|
||||
}else if(ScheduleStatusEnum.NORMAL.getValue() == vo.getStatus()) {
|
||||
ScheduleUtils.resumeJob(scheduler, scheduleJob);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package net.maku.quartz.task;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 测试定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TestTask {
|
||||
|
||||
public void run(String params) throws InterruptedException {
|
||||
log.info("我是testTask.run(),参数:{},正在被执行。", params);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package net.maku.quartz.utils;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.maku.framework.common.utils.ExceptionUtils;
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import net.maku.quartz.entity.ScheduleJobLogEntity;
|
||||
import net.maku.quartz.enums.ScheduleStatusEnum;
|
||||
import net.maku.quartz.service.ScheduleJobLogService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractScheduleJob implements Job {
|
||||
private static final ThreadLocal<Date> threadLocal = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) {
|
||||
ScheduleJobEntity scheduleJob = new ScheduleJobEntity();
|
||||
BeanUtils.copyProperties(context.getMergedJobDataMap().get(ScheduleUtils.JOB_PARAM_KEY), scheduleJob);
|
||||
|
||||
try {
|
||||
threadLocal.set(new Date());
|
||||
doExecute(scheduleJob);
|
||||
saveLog(scheduleJob, null);
|
||||
} catch (Exception e) {
|
||||
log.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e);
|
||||
saveLog(scheduleJob, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行spring bean方法
|
||||
*/
|
||||
protected void doExecute(ScheduleJobEntity scheduleJob) throws Exception {
|
||||
log.info("准备执行任务,任务ID:{}", scheduleJob.getId());
|
||||
|
||||
Object bean = SpringUtil.getBean(scheduleJob.getBeanName());
|
||||
Method method = bean.getClass().getDeclaredMethod(scheduleJob.getMethod(), String.class);
|
||||
method.invoke(bean, scheduleJob.getParams());
|
||||
|
||||
log.info("任务执行完毕,任务ID:{}", scheduleJob.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 log
|
||||
*/
|
||||
protected void saveLog(ScheduleJobEntity scheduleJob, Exception e) {
|
||||
Date startTime = threadLocal.get();
|
||||
threadLocal.remove();
|
||||
|
||||
// 执行总时长
|
||||
long times = System.currentTimeMillis() - startTime.getTime();
|
||||
|
||||
// 保存执行记录
|
||||
ScheduleJobLogEntity log = new ScheduleJobLogEntity();
|
||||
log.setJobId(scheduleJob.getId());
|
||||
log.setJobName(scheduleJob.getJobName());
|
||||
log.setJobGroup(scheduleJob.getJobGroup());
|
||||
log.setBeanName(scheduleJob.getBeanName());
|
||||
log.setMethod(scheduleJob.getMethod());
|
||||
log.setParams(scheduleJob.getParams());
|
||||
log.setTimes(times);
|
||||
log.setCreateTime(new Date());
|
||||
|
||||
if (e != null) {
|
||||
log.setStatus(ScheduleStatusEnum.PAUSE.getValue());
|
||||
String error = StringUtils.substring(ExceptionUtils.getExceptionMessage(e), 0, 2000);
|
||||
log.setError(error);
|
||||
} else {
|
||||
log.setStatus(ScheduleStatusEnum.NORMAL.getValue());
|
||||
}
|
||||
|
||||
// 保存日志
|
||||
SpringUtil.getBean(ScheduleJobLogService.class).save(log);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package net.maku.quartz.utils;
|
||||
|
||||
import org.quartz.CronExpression;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* cron 工具类
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*
|
||||
*/
|
||||
public class CronUtils {
|
||||
/**
|
||||
* 验证Cron表达式是否有效
|
||||
*/
|
||||
public static boolean isValid(String cronExpression) {
|
||||
return CronExpression.isValidExpression(cronExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的Cron表达式,返回下一个执行时间
|
||||
*/
|
||||
public static Date getNextExecution(String cronExpression) {
|
||||
try {
|
||||
CronExpression cron = new CronExpression(cronExpression);
|
||||
return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.maku.quartz.utils;
|
||||
|
||||
/**
|
||||
* 允许并发(不会等待上一次任务执行完毕,只要时间到就会执行)
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*
|
||||
*/
|
||||
public class ScheduleConcurrentExecution extends AbstractScheduleJob {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package net.maku.quartz.utils;
|
||||
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
|
||||
/**
|
||||
* 禁止并发
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*
|
||||
*/
|
||||
@DisallowConcurrentExecution
|
||||
public class ScheduleDisallowConcurrentExecution extends AbstractScheduleJob {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
package net.maku.quartz.utils;
|
||||
|
||||
import net.maku.framework.common.exception.FastException;
|
||||
import net.maku.quartz.entity.ScheduleJobEntity;
|
||||
import net.maku.quartz.enums.ScheduleConcurrentEnum;
|
||||
import net.maku.quartz.enums.ScheduleStatusEnum;
|
||||
import org.quartz.*;
|
||||
|
||||
/**
|
||||
* 定时任务工具类
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
public class ScheduleUtils {
|
||||
private final static String JOB_NAME = "TASK_NAME_";
|
||||
/**
|
||||
* 任务调度参数key
|
||||
*/
|
||||
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
|
||||
|
||||
/**
|
||||
* 获取quartz任务类
|
||||
*/
|
||||
public static Class<? extends Job> getJobClass(ScheduleJobEntity scheduleJob) {
|
||||
if(scheduleJob.getConcurrent().equals(ScheduleConcurrentEnum.NO.getValue())){
|
||||
return ScheduleDisallowConcurrentExecution.class;
|
||||
}else {
|
||||
return ScheduleConcurrentExecution.class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取触发器key
|
||||
*/
|
||||
public static TriggerKey getTriggerKey(ScheduleJobEntity scheduleJob) {
|
||||
return TriggerKey.triggerKey(JOB_NAME + scheduleJob.getId(), scheduleJob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jobKey
|
||||
*/
|
||||
public static JobKey getJobKey(ScheduleJobEntity scheduleJob) {
|
||||
return JobKey.jobKey(JOB_NAME + scheduleJob.getId(), scheduleJob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建定时任务
|
||||
*/
|
||||
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
// job key
|
||||
JobKey jobKey = getJobKey(scheduleJob);
|
||||
// 构建job信息
|
||||
JobDetail jobDetail = JobBuilder.newJob(getJobClass(scheduleJob)).withIdentity(jobKey).build();
|
||||
|
||||
// 表达式调度构建器
|
||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
||||
.withMisfireHandlingInstructionDoNothing();
|
||||
|
||||
// 按新的cronExpression表达式构建一个新的trigger
|
||||
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob))
|
||||
.withSchedule(scheduleBuilder).build();
|
||||
|
||||
// 放入参数,运行时的方法可以获取
|
||||
jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
|
||||
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
|
||||
// 判断是否存在
|
||||
if (scheduler.checkExists(jobKey)){
|
||||
// 防止创建时存在数据问题,先移除,然后再执行创建操作
|
||||
scheduler.deleteJob(jobKey);
|
||||
}
|
||||
|
||||
// 判断任务是否过期
|
||||
if (CronUtils.getNextExecution(scheduleJob.getCronExpression()) != null){
|
||||
// 执行调度任务
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
}
|
||||
|
||||
// 暂停任务
|
||||
if (scheduleJob.getStatus().equals(ScheduleStatusEnum.PAUSE.getValue())){
|
||||
scheduler.pauseJob(jobKey);
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
throw new FastException("创建定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 立即执行任务
|
||||
*/
|
||||
public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
// 参数
|
||||
JobDataMap dataMap = new JobDataMap();
|
||||
dataMap.put(JOB_PARAM_KEY, scheduleJob);
|
||||
|
||||
JobKey jobKey = getJobKey(scheduleJob);
|
||||
if (scheduler.checkExists(jobKey)) {
|
||||
scheduler.triggerJob(jobKey, dataMap);
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
throw new FastException("执行定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停任务
|
||||
*/
|
||||
public static void pauseJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
scheduler.pauseJob(getJobKey(scheduleJob));
|
||||
} catch (SchedulerException e) {
|
||||
throw new FastException("暂停定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务
|
||||
*/
|
||||
public static void resumeJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
scheduler.resumeJob(getJobKey(scheduleJob));
|
||||
} catch (SchedulerException e) {
|
||||
throw new FastException("恢复定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新定时任务
|
||||
*/
|
||||
public static void updateSchedulerJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
// 判断是否存在
|
||||
JobKey jobKey = ScheduleUtils.getJobKey(scheduleJob);
|
||||
|
||||
try {
|
||||
// 防止创建时存在数据问题,先移除,然后再执行创建操作
|
||||
if (scheduler.checkExists(jobKey)) {
|
||||
scheduler.deleteJob(jobKey);
|
||||
}
|
||||
}catch (SchedulerException e){
|
||||
throw new FastException("更新定时任务失败", e);
|
||||
}
|
||||
|
||||
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除定时任务
|
||||
*/
|
||||
public static void deleteScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
scheduler.deleteJob(getJobKey(scheduleJob));
|
||||
} catch (SchedulerException e) {
|
||||
throw new FastException("删除定时任务失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package net.maku.quartz.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import net.maku.framework.common.utils.DateUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "定时任务日志")
|
||||
public class ScheduleJobLogVO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "任务id")
|
||||
private Long jobId;
|
||||
|
||||
@Schema(description = "任务名称")
|
||||
private String jobName;
|
||||
|
||||
@Schema(description = "任务组名")
|
||||
private String jobGroup;
|
||||
|
||||
@Schema(description = "spring bean名称")
|
||||
private String beanName;
|
||||
|
||||
@Schema(description = "执行方法")
|
||||
private String method;
|
||||
|
||||
@Schema(description = "参数")
|
||||
private String params;
|
||||
|
||||
@Schema(description = "任务状态")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "异常信息")
|
||||
private String error;
|
||||
|
||||
@Schema(description = "耗时(单位:毫秒)")
|
||||
private Integer times;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package net.maku.quartz.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import net.maku.framework.common.utils.DateUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "定时任务")
|
||||
public class ScheduleJobVO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "任务名称")
|
||||
private String jobName;
|
||||
|
||||
@Schema(description = "任务组名")
|
||||
private String jobGroup;
|
||||
|
||||
@Schema(description = "bean名称")
|
||||
private String beanName;
|
||||
|
||||
@Schema(description = "执行方法")
|
||||
private String method;
|
||||
|
||||
@Schema(description = "参数")
|
||||
private String params;
|
||||
|
||||
@Schema(description = "cron表达式")
|
||||
private String cronExpression;
|
||||
|
||||
@Schema(description = "状态 ")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否并发")
|
||||
private Integer concurrent;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>net.maku</groupId>
|
||||
<artifactId>fast-boot</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>fast-boot-module</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>fast-boot-quartz</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
@ -20,6 +20,11 @@
|
|||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
</dependency>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package net.maku.framework.common.utils;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* Exception工具类
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
public class ExceptionUtils {
|
||||
|
||||
/**
|
||||
* 获取异常信息
|
||||
* @param e 异常
|
||||
* @return 返回异常信息
|
||||
*/
|
||||
public static String getExceptionMessage(Exception e) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw, true);
|
||||
e.printStackTrace(pw);
|
||||
|
||||
// 关闭IO流
|
||||
IoUtil.close(pw);
|
||||
IoUtil.close(sw);
|
||||
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,11 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.maku</groupId>
|
||||
<artifactId>fast-boot-quartz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.maku</groupId>
|
||||
<artifactId>fast-boot-system</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
|
|
|||
10
pom.xml
10
pom.xml
|
|
@ -19,17 +19,20 @@
|
|||
<modules>
|
||||
<module>fast-boot-new</module>
|
||||
<module>fast-boot-system</module>
|
||||
<module>fast-boot-module</module>
|
||||
<module>fast-boot-api</module>
|
||||
<module>fast-framework</module>
|
||||
<module>fast-server</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<revision>1.2.0</revision>
|
||||
<revision>1.3.0</revision>
|
||||
<skipTests>true</skipTests>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<mybatisplus.version>3.5.2</mybatisplus.version>
|
||||
<dameng.version>8.1.2.79</dameng.version>
|
||||
<knife4j.version>3.0.3</knife4j.version>
|
||||
<springdoc.version>1.6.8</springdoc.version>
|
||||
<hutool.version>5.7.22</hutool.version>
|
||||
|
|
@ -72,6 +75,11 @@
|
|||
<version>${mybatisplus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.dameng</groupId>
|
||||
<artifactId>DmJdbcDriver18</artifactId>
|
||||
<version>${dameng.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-springdoc-ui</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user