From a5fe1ddf58850850195dc1d3a5a3a567e114d78c Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Tue, 5 Dec 2023 16:40:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/njcn/autocode/utils/GenerateCode.java | 8 +- .../njcn/system/enums/SystemResponseEnum.java | 7 +- .../system/pojo/enums/TimerJobStatusEnum.java | 31 ++++ .../njcn/system/pojo/param/TimersParam.java | 56 ++++++ .../java/com/njcn/system/pojo/po/Timers.java | 64 +++++++ .../com/njcn/system/pojo/vo/TimersVO.java | 53 ++++++ .../system/controller/TimersController.java | 168 ++++++++++++++++++ .../com/njcn/system/mapper/TimersMapper.java | 22 +++ .../system/mapper/mapping/TimersMapper.xml | 12 ++ .../njcn/system/service/ITimersService.java | 34 ++++ .../service/impl/TimersServiceImpl.java | 142 +++++++++++++++ .../njcn/system/timer/TimerExeService.java | 35 ++++ .../system/timer/TimerTaskInitListener.java | 55 ++++++ .../njcn/system/timer/TimerTaskRunner.java | 19 ++ .../timer/impl/HutoolTimerExeServiceImpl.java | 59 ++++++ .../system/timer/tasks/DemoTaskRunner.java | 28 +++ 16 files changed, 788 insertions(+), 5 deletions(-) create mode 100644 pqs-system/system-api/src/main/java/com/njcn/system/pojo/enums/TimerJobStatusEnum.java create mode 100644 pqs-system/system-api/src/main/java/com/njcn/system/pojo/param/TimersParam.java create mode 100644 pqs-system/system-api/src/main/java/com/njcn/system/pojo/po/Timers.java create mode 100644 pqs-system/system-api/src/main/java/com/njcn/system/pojo/vo/TimersVO.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/controller/TimersController.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/mapper/TimersMapper.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/mapper/mapping/TimersMapper.xml create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/service/ITimersService.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/service/impl/TimersServiceImpl.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerExeService.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskInitListener.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskRunner.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/timer/impl/HutoolTimerExeServiceImpl.java create mode 100644 pqs-system/system-boot/src/main/java/com/njcn/system/timer/tasks/DemoTaskRunner.java diff --git a/pqs-common/common-autocode/src/main/java/com/njcn/autocode/utils/GenerateCode.java b/pqs-common/common-autocode/src/main/java/com/njcn/autocode/utils/GenerateCode.java index 1a5d5b0f9..695604576 100644 --- a/pqs-common/common-autocode/src/main/java/com/njcn/autocode/utils/GenerateCode.java +++ b/pqs-common/common-autocode/src/main/java/com/njcn/autocode/utils/GenerateCode.java @@ -21,7 +21,7 @@ public class GenerateCode { private static final String TARGET_DIR = "D://code"; - private static final String DB_URL = "jdbc:mysql://192.168.1.18:13306/pqsinfo_sjzx_zl"; + private static final String DB_URL = "jdbc:mysql://192.168.1.18:13306/pqsinfo"; private static final String USERNAME = "root"; @@ -30,9 +30,9 @@ public class GenerateCode { public static void main(String[] args) { List modules = Stream.of( - new Module("hongawen", "com.njcn.mybatis", "advance", Stream.of( - "rocketmq_msg_error_log" - ).collect(Collectors.toList()), "pqs") + new Module("hongawen", "com.njcn.system", "timer", Stream.of( + "sys_timers" + ).collect(Collectors.toList()), "sys") ).collect(Collectors.toList()); generateJavaFile(modules); } diff --git a/pqs-system/system-api/src/main/java/com/njcn/system/enums/SystemResponseEnum.java b/pqs-system/system-api/src/main/java/com/njcn/system/enums/SystemResponseEnum.java index 48b09d410..7c357e917 100644 --- a/pqs-system/system-api/src/main/java/com/njcn/system/enums/SystemResponseEnum.java +++ b/pqs-system/system-api/src/main/java/com/njcn/system/enums/SystemResponseEnum.java @@ -43,9 +43,14 @@ public enum SystemResponseEnum { ADVANCE_REASON("A00370","查询字典暂降原因为空"), EFFECT_STATUS_EMPTY("A00370","查询字典实施状态为空"), - EVENT_REPORT_REPEAT("A00361","暂态报告模板重复"), + NOT_EXISTED("A00361", "您查询的该条记录不存在"), + /** + * 定时任务执行类不存在 + */ + TIMER_NOT_EXISTED("A00361", "定时任务执行类不存在"), + EXE_EMPTY_PARAM("A00361", "请检查定时器的id,定时器cron表达式,定时任务是否为空!") ; private final String code; diff --git a/pqs-system/system-api/src/main/java/com/njcn/system/pojo/enums/TimerJobStatusEnum.java b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/enums/TimerJobStatusEnum.java new file mode 100644 index 000000000..342faa22a --- /dev/null +++ b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/enums/TimerJobStatusEnum.java @@ -0,0 +1,31 @@ + +package com.njcn.system.pojo.enums; + +import lombok.Getter; + +/** + * 定时任务的状态 + * + * @author hongawen + * @date 2020/6/30 20:44 + */ +@Getter +public enum TimerJobStatusEnum { + + /** + * 启动状态 + */ + RUNNING(1), + + /** + * 停止状态 + */ + STOP(2); + + private final Integer code; + + TimerJobStatusEnum(int code) { + this.code = code; + } + +} diff --git a/pqs-system/system-api/src/main/java/com/njcn/system/pojo/param/TimersParam.java b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/param/TimersParam.java new file mode 100644 index 000000000..2e983b1fa --- /dev/null +++ b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/param/TimersParam.java @@ -0,0 +1,56 @@ +package com.njcn.system.pojo.param; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import com.njcn.web.constant.ValidMessage; +import com.njcn.web.pojo.param.BaseParam; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; + +/** + *

+ * 定时任务 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +@Data +public class TimersParam extends BaseParam { + + private static final long serialVersionUID = 1L; + + /** + * 定时器id + */ + @NotBlank(message = ValidMessage.ID_NOT_BLANK) + private String id; + + /** + * 任务名称 + */ + private String timerName; + + /** + * 执行任务的class的类名(实现了TimerTaskRunner接口的类的全称) + */ + private String actionClass; + + /** + * 定时任务表达式 + */ + private String cron; + + /** + * 状态(字典 1运行 2停止) + */ + private Integer jobStatus; + + /** + * 备注信息 + */ + private String remark; + +} diff --git a/pqs-system/system-api/src/main/java/com/njcn/system/pojo/po/Timers.java b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/po/Timers.java new file mode 100644 index 000000000..23c8f05fc --- /dev/null +++ b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/po/Timers.java @@ -0,0 +1,64 @@ +package com.njcn.system.pojo.po; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import java.io.Serializable; +import java.time.LocalDateTime; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 定时任务 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_timers") +public class Timers extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 定时器id + */ + private String id; + + /** + * 任务名称 + */ + private String timerName; + + /** + * 执行任务的class的类名(实现了TimerTaskRunner接口的类的全称) + */ + private String actionClass; + + /** + * 定时任务表达式 + */ + private String cron; + + /** + * 状态(字典 1运行 2停止) + */ + private Integer jobStatus; + + /** + * 备注信息 + */ + private String remark; + + + /** + * 状态:0-删除 1-正常 + */ + private Integer state; + +} diff --git a/pqs-system/system-api/src/main/java/com/njcn/system/pojo/vo/TimersVO.java b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/vo/TimersVO.java new file mode 100644 index 000000000..173493b3f --- /dev/null +++ b/pqs-system/system-api/src/main/java/com/njcn/system/pojo/vo/TimersVO.java @@ -0,0 +1,53 @@ +package com.njcn.system.pojo.vo; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 定时任务 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +@Data +public class TimersVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 定时器id + */ + private String id; + + /** + * 任务名称 + */ + private String timerName; + + /** + * 执行任务的class的类名(实现了TimerTaskRunner接口的类的全称) + */ + private String actionClass; + + /** + * 定时任务表达式 + */ + private String cron; + + /** + * 状态(字典 1运行 2停止) + */ + private Integer jobStatus; + + /** + * 备注信息 + */ + private String remark; + +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/controller/TimersController.java b/pqs-system/system-boot/src/main/java/com/njcn/system/controller/TimersController.java new file mode 100644 index 000000000..a8fc0a14f --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/controller/TimersController.java @@ -0,0 +1,168 @@ +package com.njcn.system.controller; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.common.pojo.annotation.OperateInfo; +import com.njcn.common.pojo.constant.OperateType; +import com.njcn.common.pojo.enums.common.LogEnum; +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.common.utils.HttpResultUtil; +import com.njcn.common.utils.LogUtil; +import com.njcn.system.pojo.param.TimersParam; +import com.njcn.system.pojo.vo.TimersVO; +import com.njcn.system.service.ITimersService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.njcn.web.controller.BaseController; + +import java.util.List; + +/** + *

+ * 定时任务 前端控制器 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +@Slf4j +@RestController +@RequestMapping("/timer") +@Api(tags = "定时任务管理中心") +@AllArgsConstructor +public class TimersController extends BaseController { + + + private final ITimersService timersService; + + /** + * 分页查询定时任务 + * + * @author hongawen + */ + @PostMapping("/list") + @OperateInfo(info = LogEnum.SYSTEM_COMMON) + @ApiOperation("查询定时任务") + @ApiImplicitParam(name = "timersParam", value = "查询参数", required = true) + public HttpResult> list(@RequestBody TimersParam timersParam) { + String methodDescribe = getMethodDescribe("list"); + Page result = timersService.listTimer(timersParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe); + } + + /** + * 添加定时任务 + * + * @author hongawen + */ + @PostMapping("/add") + @ApiOperation("新增定时任务") + @OperateInfo(info = LogEnum.SYSTEM_COMMON, operateType = OperateType.ADD) + @ApiImplicitParam(name = "timersParam", value = "定时任务信息", required = true) + public HttpResult add(@RequestBody TimersParam timersParam) { + String methodDescribe = getMethodDescribe("add"); + boolean flag = timersService.addTimer(timersParam); + if (flag) { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 编辑定时任务 + * + * @author hongawen + */ + @OperateInfo(info = LogEnum.SYSTEM_COMMON, operateType = OperateType.UPDATE) + @PostMapping("/update") + @ApiOperation("修改定时任务") + @ApiImplicitParam(name = "timersParam", value = "定时任务信息", required = true) + public HttpResult update(@RequestBody @Validated TimersParam timersParam) { + String methodDescribe = getMethodDescribe("update"); + boolean flag = timersService.editTimer(timersParam); + if (flag) { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + + /** + * 删除定时任务 + * + * @author hongawen + */ + @PostMapping("/delete") + @OperateInfo(info = LogEnum.SYSTEM_COMMON, operateType = OperateType.UPDATE) + @ApiOperation("删除定时任务") + @ApiImplicitParam(name = "ids", value = "id集合", required = true, dataTypeClass = List.class) + public HttpResult delete(@RequestBody List ids) { + String methodDescribe = getMethodDescribe("delete"); + LogUtil.njcnDebug(log, "{},任务ID数据为:{}", methodDescribe, String.join(StrUtil.COMMA, ids)); + boolean result = timersService.deleteTimers(ids); + if (result) { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + + /** + * 获取系统的所有任务列表 + * + * @author hongawen + */ + @OperateInfo(info = LogEnum.SYSTEM_COMMON) + @GetMapping("/getActionClasses") + @ApiOperation("获取所有任务列表") + public HttpResult> getActionClasses() { + String methodDescribe = getMethodDescribe("getActionClasses"); + List actionClasses = timersService.getActionClasses(); + if (CollectionUtil.isNotEmpty(actionClasses)) { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, actionClasses, methodDescribe); + } else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 启动定时任务 + * + * @author hongawen + */ + @OperateInfo(info = LogEnum.SYSTEM_COMMON, operateType = OperateType.UPDATE) + @GetMapping("/start") + @ApiOperation("启动定时任务") + public HttpResult start(String id) { + String methodDescribe = getMethodDescribe("start"); + timersService.start(id); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } + + /** + * 停止定时任务 + * + * @author hongawen + */ + @OperateInfo(info = LogEnum.SYSTEM_COMMON, operateType = OperateType.UPDATE) + @GetMapping("/stop") + @ApiOperation("关闭定时任务") + public HttpResult stop(String id) { + String methodDescribe = getMethodDescribe("stop"); + timersService.stop(id); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + } + +} + diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/mapper/TimersMapper.java b/pqs-system/system-boot/src/main/java/com/njcn/system/mapper/TimersMapper.java new file mode 100644 index 000000000..1edd8eae9 --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/mapper/TimersMapper.java @@ -0,0 +1,22 @@ +package com.njcn.system.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.system.pojo.po.Timers; +import com.njcn.system.pojo.vo.DictDataVO; +import com.njcn.system.pojo.vo.TimersVO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 定时任务 Mapper 接口 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +public interface TimersMapper extends BaseMapper { + + Page page(@Param("page") Page page, @Param("ew") QueryWrapper queryWrapper); +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/mapper/mapping/TimersMapper.xml b/pqs-system/system-boot/src/main/java/com/njcn/system/mapper/mapping/TimersMapper.xml new file mode 100644 index 000000000..7aa35c66e --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/mapper/mapping/TimersMapper.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/service/ITimersService.java b/pqs-system/system-boot/src/main/java/com/njcn/system/service/ITimersService.java new file mode 100644 index 000000000..6610ffb9c --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/service/ITimersService.java @@ -0,0 +1,34 @@ +package com.njcn.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.system.pojo.param.TimersParam; +import com.njcn.system.pojo.po.Timers; +import com.njcn.system.pojo.vo.TimersVO; + +import java.util.List; + +/** + *

+ * 定时任务 服务类 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +public interface ITimersService extends IService { + + Page listTimer(TimersParam queryParam); + + boolean addTimer(TimersParam timersParam); + + boolean editTimer(TimersParam timersParam); + + boolean deleteTimers(List ids); + + List getActionClasses(); + + void start(String id); + + void stop(String id); +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/service/impl/TimersServiceImpl.java b/pqs-system/system-boot/src/main/java/com/njcn/system/service/impl/TimersServiceImpl.java new file mode 100644 index 000000000..a278428c9 --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/service/impl/TimersServiceImpl.java @@ -0,0 +1,142 @@ +package com.njcn.system.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.njcn.common.pojo.enums.common.DataStateEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.db.constant.DbConstant; +import com.njcn.system.enums.SystemResponseEnum; +import com.njcn.system.mapper.TimersMapper; +import com.njcn.system.pojo.enums.TimerJobStatusEnum; +import com.njcn.system.pojo.param.TimersParam; +import com.njcn.system.pojo.po.DictData; +import com.njcn.system.pojo.po.Timers; +import com.njcn.system.pojo.vo.DictDataVO; +import com.njcn.system.pojo.vo.TimersVO; +import com.njcn.system.service.ITimersService; +import com.njcn.system.timer.TimerExeService; +import com.njcn.system.timer.TimerTaskRunner; +import com.njcn.web.factory.PageFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 定时任务 服务实现类 + *

+ * + * @author hongawen + * @since 2023-12-05 + */ +@Service +@RequiredArgsConstructor +public class TimersServiceImpl extends ServiceImpl implements ITimersService { + + private final TimerExeService timerExeService; + + @Override + public Page listTimer(TimersParam queryParam) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (ObjectUtil.isNotNull(queryParam)) { + //查询参数不为空,进行条件填充 + if (StrUtil.isNotBlank(queryParam.getSearchValue())) { + //定时任务,待提供名称、编码模糊查询 todo... + + } + } + queryWrapper.orderBy(true, true, "sys_timers.create_time"); + queryWrapper.ne("sys_timers.state", DataStateEnum.DELETED.getCode()); + //初始化分页数据 + return this.baseMapper.page(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper); + } + + @Override + public boolean addTimer(TimersParam timersParam) { + Timers timers = new Timers(); + BeanUtil.copyProperties(timersParam, timers); + //默认为正常状态 + timers.setState(DataStateEnum.ENABLE.getCode()); + return this.save(timers); + } + + @Override + public boolean editTimer(TimersParam timersParam) { + Timers timers = new Timers(); + BeanUtil.copyProperties(timersParam, timers); + return this.updateById(timers); + } + + @Override + public boolean deleteTimers(List ids) { + return this.lambdaUpdate() + .set(Timers::getState, DataStateEnum.DELETED.getCode()) + .in(Timers::getId, ids) + .update(); + } + + @Override + public List getActionClasses() { + Map timerTaskRunnerMap = SpringUtil.getBeansOfType(TimerTaskRunner.class); + if (ObjectUtil.isNotEmpty(timerTaskRunnerMap)) { + Collection values = timerTaskRunnerMap.values(); + return values.stream().map(i -> i.getClass().getName()).collect(Collectors.toList()); + } else { + return CollectionUtil.newArrayList(); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void start(String id) { + // 更新库中的状态 + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.set(Timers::getJobStatus, TimerJobStatusEnum.RUNNING.getCode()) + .eq(Timers::getId,id); + this.update(wrapper); + + // 添加定时任务调度 + Timers sysTimers = this.queryTimers(id); + timerExeService.startTimer(sysTimers.getId(), sysTimers.getCron(), sysTimers.getActionClass()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void stop(String id) { + // 更新库中的状态 + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.set(Timers::getJobStatus, TimerJobStatusEnum.STOP.getCode()) + .eq(Timers::getId, id); + this.update(wrapper); + // 关闭定时任务调度 + Timers sysTimers = this.queryTimers(id); + timerExeService.stopTimer(sysTimers.getId()); + } + + /** + * 获取定时任务 + * + * @author hongawen + * @date 2020/6/30 18:26 + */ + private Timers queryTimers(String id) { + Timers timers = this.getById(id); + if (ObjectUtil.isEmpty(timers)) { + throw new BusinessException(SystemResponseEnum.NOT_EXISTED); + } + return timers; + } + +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerExeService.java b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerExeService.java new file mode 100644 index 000000000..4deb42ac4 --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerExeService.java @@ -0,0 +1,35 @@ + +package com.njcn.system.timer; + +import com.njcn.system.pojo.param.TimersParam; + +/** + * 本接口用来,屏蔽定时任务的多样性 + * 目前用hutool + * @author hongawen + */ +public interface TimerExeService { + + /** + * 启动一个定时器 + *

+ * 定时任务表达式书写规范:0/2 * * * * * + *

+ * 六位数,分别是:秒 分 小时 日 月 年 + * + * @param taskId 任务id + * @param cron cron表达式 + * @param className 类的全名,必须是TimerTaskRunner的子类 + * @author hongawen + */ + void startTimer(String taskId, String cron, String className); + + /** + * 停止一个定时器 + * + * @param taskId 定时任务Id + * @author hongawen + */ + void stopTimer(String taskId); + +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskInitListener.java b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskInitListener.java new file mode 100644 index 000000000..c0b1e76a6 --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskInitListener.java @@ -0,0 +1,55 @@ + +package com.njcn.system.timer; + +import cn.hutool.cron.CronUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.njcn.common.pojo.enums.common.DataStateEnum; +import com.njcn.system.pojo.enums.TimerJobStatusEnum; +import com.njcn.system.pojo.param.TimersParam; +import com.njcn.system.pojo.po.Timers; +import com.njcn.system.service.ITimersService; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author : hongawen + */ +@Component +public class TimerTaskInitListener implements ApplicationRunner, Ordered { + + /** + * + * @param args incoming application arguments + */ + @Override + public void run(ApplicationArguments args) { + ITimersService sysTimersService = SpringUtil.getBean(ITimersService.class); + TimerExeService timerExeService = SpringUtil.getBean(TimerExeService.class); + // 获取所有开启状态的任务 + LambdaQueryWrapper lambdaQueryChainWrapper = new LambdaQueryWrapper<>(); + lambdaQueryChainWrapper.eq(Timers::getJobStatus,TimerJobStatusEnum.RUNNING.getCode()) + .ne(Timers::getState, DataStateEnum.DELETED.getCode()); + List list = sysTimersService.list(lambdaQueryChainWrapper); + // 添加定时任务到调度器 + for (Timers sysTimers : list) { + timerExeService.startTimer(String.valueOf(sysTimers.getId()), sysTimers.getCron(), sysTimers.getActionClass()); + } + + // 设置秒级别的启用 + CronUtil.setMatchSecond(true); + + // 启动定时器执行器 + CronUtil.start(); + } + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE-10; + } +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskRunner.java b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskRunner.java new file mode 100644 index 000000000..39d45878d --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/TimerTaskRunner.java @@ -0,0 +1,19 @@ + +package com.njcn.system.timer; + +/** + * 定时器执行者 + *

+ * 定时器都要实现本接口,并需要把实现类加入到spring容器中 + * + */ +public interface TimerTaskRunner { + + /** + * 任务执行的具体内容 + * + * @author hongawen + */ + void action(); + +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/timer/impl/HutoolTimerExeServiceImpl.java b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/impl/HutoolTimerExeServiceImpl.java new file mode 100644 index 000000000..5dff9dcbc --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/impl/HutoolTimerExeServiceImpl.java @@ -0,0 +1,59 @@ + +package com.njcn.system.timer.impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.cron.CronUtil; +import cn.hutool.cron.task.Task; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.log.Log; +import cn.hutool.setting.Setting; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.system.enums.SystemResponseEnum; +import com.njcn.system.timer.TimerExeService; +import com.njcn.system.timer.TimerTaskRunner; +import org.springframework.stereotype.Service; + +/** + * hutool方式的定时任务执行 + * + * @author hongawen + */ +@Service +public class HutoolTimerExeServiceImpl implements TimerExeService { + + private static final Log log = Log.get(); + + @Override + public void startTimer(String taskId, String cron, String className) { + + if (ObjectUtil.hasEmpty(taskId, cron, className)) { + throw new BusinessException(SystemResponseEnum.EXE_EMPTY_PARAM); + } + + // 预加载类看是否存在此定时任务类 + try { + Class.forName(className); + } catch (ClassNotFoundException e) { + throw new BusinessException(SystemResponseEnum.TIMER_NOT_EXISTED); + } + + // 定义hutool的任务 + Task task = () -> { + try { + TimerTaskRunner timerTaskRunner = (TimerTaskRunner) SpringUtil.getBean(Class.forName(className)); + timerTaskRunner.action(); + } catch (ClassNotFoundException e) { + log.error(">>> 任务执行异常:{}", e.getMessage()); + } + }; + + // 开始执行任务 + CronUtil.schedule(taskId, cron, task); + } + + @Override + public void stopTimer(String taskId) { + CronUtil.remove(taskId); + } + +} diff --git a/pqs-system/system-boot/src/main/java/com/njcn/system/timer/tasks/DemoTaskRunner.java b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/tasks/DemoTaskRunner.java new file mode 100644 index 000000000..a4da8360f --- /dev/null +++ b/pqs-system/system-boot/src/main/java/com/njcn/system/timer/tasks/DemoTaskRunner.java @@ -0,0 +1,28 @@ + +package com.njcn.system.timer.tasks; + +import com.njcn.system.timer.TimerTaskRunner; +import org.springframework.stereotype.Component; + + +/** + * 定时同步用户数据 + * + * @author hongawen + * @date 2020/6/30 22:09 + */ +@Component +public class DemoTaskRunner implements TimerTaskRunner { + + + + + @Override + public void action() { + + //定时同步用户数据 + System.out.println("定时输出一段文字"); + + } + +}