新增定时任务

This commit is contained in:
阿沐 2022-08-04 09:28:41 +08:00
parent 7587a053c4
commit b241dd45cd
35 changed files with 1708 additions and 265 deletions

View File

@ -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

View File

@ -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 = '同步机制的行锁表';

View File

@ -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
```

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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> {
}

View File

@ -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> {
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}
}

View File

@ -0,0 +1,11 @@
package net.maku.quartz.utils;
/**
* 允许并发不会等待上一次任务执行完毕只要时间到就会执行
*
* @author 阿沐 babamu@126.com
*
*/
public class ScheduleConcurrentExecution extends AbstractScheduleJob {
}

View File

@ -0,0 +1,14 @@
package net.maku.quartz.utils;
import org.quartz.DisallowConcurrentExecution;
/**
* 禁止并发
*
* @author 阿沐 babamu@126.com
*
*/
@DisallowConcurrentExecution
public class ScheduleDisallowConcurrentExecution extends AbstractScheduleJob {
}

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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;
}

15
fast-boot-module/pom.xml Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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
View File

@ -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>