云
11 小时以前 41ba09635ca0e5d79117a4364c25b1a5e93c4f13
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
@@ -6,6 +6,7 @@
import org.quartz.*;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;
@@ -31,6 +32,10 @@
        try {
            JobDetail jobDetail = buildJobDetail(task);
            Trigger trigger = buildJobTrigger(task, jobDetail);
            if (scheduler.checkExists(jobDetail.getKey())) {
                // 持久化的Job可能还在(例如历史数据直接写入、上次未清理),先移除旧的Job及其触发器
                scheduler.deleteJob(jobDetail.getKey());
            }
            scheduler.scheduleJob(jobDetail, trigger);
        }catch (SchedulerException e){
            log.error("SchedulerException scheduleMaintenanceTask ERROR",e);
@@ -45,30 +50,49 @@
       try{
           TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId());
           // 获取现有触发器并转换为 CronTrigger
           // 获取现有触发器
           Trigger oldTrigger = scheduler.getTrigger(triggerKey);
           if (!(oldTrigger instanceof CronTrigger)) {
               throw new SchedulerException("Existing trigger is not a CronTrigger");
               // 触发器不存在或类型不符(如任务由直接写库创建),重新注册而不是报错
               scheduleMaintenanceTask(task);
               return;
           }
           // 3. 构建CronTrigger,确保持久化配置
           // 构建CronTrigger,确保持久化配置
           CronTrigger newTrigger = TriggerBuilder.newTrigger()
                   .withIdentity(triggerKey)                // 唯一标识,用于持久化存储
                   .withDescription(task.getTaskName() + "_TRIGGER") // 触发器描述
                   .forJob(oldTrigger.getJobKey())                       // 关联对应的Job
                   .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())
                   // 设置开始时间(若为null或已过期则立即生效)
                   .startAt(resolveStartTime(task))
                   .build();
           scheduler.rescheduleJob(triggerKey, newTrigger);
       }catch (SchedulerException e){
           log.error("SchedulerException rescheduleMaintenanceTask ERROR",e);
           throw new RuntimeException(e);
       }
    }
    /**
     * 判断任务是否已注册到调度器
     */
    public boolean isRegistered(Long taskId) throws SchedulerException {
        return scheduler.checkExists(new TriggerKey("triggerMaintenanceTask_" + taskId));
    }
    /**
     * 触发器开始时间:为空或已过期时从当前时间起算,避免补跑历史
     */
    private Date resolveStartTime(MaintenanceTask task) {
        LocalDateTime nextExecutionTime = task.getNextExecutionTime();
        if (nextExecutionTime == null || !nextExecutionTime.isAfter(LocalDateTime.now())) {
            return new Date();
        }
        return Date.from(nextExecutionTime.atZone(ZoneId.systemDefault()).toInstant());
    }
    /**
@@ -137,10 +161,8 @@
                        .cronSchedule(cronExpression)
                        .withMisfireHandlingInstructionDoNothing() // 错过执行时的策略(根据业务调整)
                )
                // 4. 设置开始时间(若为null则立即生效)
                .startAt(task.getNextExecutionTime() != null
                        ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())
                        : new Date())
                // 4. 设置开始时间(若为null或已过期则立即生效)
                .startAt(resolveStartTime(task))
                .build();
    }
    private String convertToCronExpression(MaintenanceTask task) {