gongchunyi
8 天以前 0dc3779c31af4f070d3dfec5cc9910d9caa7687c
fix: 修改定时任务报错、任务可以开启和关闭、删除时移除定时任务
已修改3个文件
98 ■■■■ 文件已修改
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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("删除失败");
    }
}