src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -62,8 +62,8 @@ @Schema(description = "最后执行时间") private LocalDateTime lastExecutionTime; @Schema(description = "是否激活") private boolean isActive; @Schema(description = "是否激活, 1=启用, 0=停用") private Integer isActive; @Schema(description = "备注") @Excel(name = "备注") src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
@@ -25,13 +25,25 @@ private final Scheduler scheduler; /** * 添加新任务到调度器 * 添加或更新任务到调度器 */ public void scheduleMaintenanceTask(MaintenanceTask task){ try { JobDetail jobDetail = buildJobDetail(task); Trigger trigger = buildJobTrigger(task, jobDetail); scheduler.scheduleJob(jobDetail, trigger); // 检查触发器是否已存在 TriggerKey triggerKey = trigger.getKey(); Trigger existingTrigger = scheduler.getTrigger(triggerKey); if (existingTrigger != null) { // 触发器已存在,更新它 scheduler.rescheduleJob(triggerKey, trigger); } else { // 触发器不存在,先确保 Job 存在,然后调度触发器 scheduler.addJob(jobDetail, true); scheduler.scheduleJob(trigger); } }catch (SchedulerException e){ log.error("SchedulerException scheduleMaintenanceTask ERROR",e); throw new RuntimeException(e); @@ -45,26 +57,41 @@ try{ TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId()); // 获取现有触发器并转换为 CronTrigger // 获取现有触发器 Trigger oldTrigger = scheduler.getTrigger(triggerKey); // 构建新的 JobDetail 和 Trigger JobDetail jobDetail = buildJobDetail(task); Trigger newTrigger = buildJobTrigger(task, jobDetail); if (oldTrigger == null) { // 触发器不存在,说明任务之前被删除过 // 先确保 Job 存在,然后调度触发器 scheduler.addJob(jobDetail, true); scheduler.scheduleJob(newTrigger); return; } // 触发器存在,直接更新 if (!(oldTrigger instanceof CronTrigger)) { throw new SchedulerException("Existing trigger is not a CronTrigger"); } // 3. 构建CronTrigger,确保持久化配置 CronTrigger newTrigger = TriggerBuilder.newTrigger() .withIdentity(triggerKey) // 唯一标识,用于持久化存储 .withDescription(task.getTaskName() + "_TRIGGER") // 触发器描述 .forJob(oldTrigger.getJobKey()) // 关联对应的Job // 构建新的 CronTrigger CronTrigger cronTrigger = TriggerBuilder.newTrigger() .withIdentity(triggerKey) .withDescription(task.getTaskName() + "_TRIGGER") .forJob(oldTrigger.getJobKey()) .withSchedule(CronScheduleBuilder .cronSchedule(convertToCronExpression(task)) // 错过执行时的策略(根据业务调整) .cronSchedule(convertToCronExpression(task)) .withMisfireHandlingInstructionDoNothing() ) // 4. 设置开始时间(若为null则立即生效) .startAt(task.getNextExecutionTime() != null ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant()) : new Date()) .build(); scheduler.rescheduleJob(triggerKey, newTrigger); scheduler.rescheduleJob(triggerKey, cronTrigger); }catch (SchedulerException e){ log.error("SchedulerException rescheduleMaintenanceTask ERROR",e); throw new RuntimeException(e); @@ -93,6 +120,7 @@ public void unscheduleMaintenanceTask(Long taskId){ try { JobKey jobKey = new JobKey("MaintenanceTask_" + taskId); // 删除 Job 会自动删除关联的 Trigger scheduler.deleteJob(jobKey); }catch (SchedulerException e){ log.error("SchedulerException unscheduleMaintenanceTask ERROR",e); src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -67,7 +67,6 @@ @Override public AjaxResult add(MaintenanceTask maintenanceTask) { maintenanceTask.setActive(true); // 计算首次执行时间 TimingTask task = new TimingTask(); task.setFrequencyType(maintenanceTask.getFrequencyType()); @@ -76,7 +75,10 @@ maintenanceTask.setNextExecutionTime(firstExecutionTime); int insert = maintenanceTaskMapper.insert(maintenanceTask); if (insert > 0) { maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask); // 只有当 isActive 为 1 时才添加到定时任务调度器 if (maintenanceTask.getIsActive() != null && maintenanceTask.getIsActive() == 1) { maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask); } } return AjaxResult.success("添加成功"); } @@ -87,22 +89,50 @@ if (maintenanceTask1 == null) { return AjaxResult.warn("没有此数据"); } // 保存旧的 isActive 状态 Integer oldIsActive = maintenanceTask1.getIsActive(); Integer newIsActive = maintenanceTask.getIsActive(); BeanUtils.copyProperties(maintenanceTask, maintenanceTask1); int update = maintenanceTaskMapper.updateById(maintenanceTask1); if (update > 0) { maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1); // 处理 isActive 状态变化 if (newIsActive != null && newIsActive == 1) { // 新状态为启用:添加到定时任务调度器 if (oldIsActive == null || oldIsActive != 1) { // 从未启用变为启用,添加到调度器 maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask1); } else { // 已经启用,更新调度器中的任务 maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1); } } else { // 新状态为停用:从定时任务调度器中移除 if (oldIsActive != null && oldIsActive == 1) { maintenanceTaskScheduler.unscheduleMaintenanceTask(maintenanceTask1.getId()); } } } return AjaxResult.success("更新成功"); } @Override public AjaxResult delete(List<Long> ids) { // 先从定时任务调度器中移除所有待删除的任务 ids.forEach(id -> { try { maintenanceTaskScheduler.unscheduleMaintenanceTask(id); } catch (Exception e) { log.error("删除定时任务调度失败, id: {}", id, e); } }); // 再从数据库中删除记录 int delete = maintenanceTaskMapper.deleteBatchIds(ids); if (delete > 0) { ids.forEach(id -> { maintenanceTaskScheduler.unscheduleMaintenanceTask(id); }); return AjaxResult.success("删除成功"); } return AjaxResult.success("删除成功"); return AjaxResult.error("删除失败"); } }