java spring boot 动态添加 cron(表达式)任务、动态添加停止单个cron任务

java spring boot 动态添加 cron(表达式)任务、动态添加停止单个cron任务

  1. 添加对应的maven

    XML 复制代码
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>
  2. 添加一个工具类 SchedulerManager

    java 复制代码
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.impl.StdSchedulerFactory;
    
    public class SchedulerManager {
        private static Scheduler scheduler;
        // 初始化 Scheduler 
        public static void initScheduler() throws SchedulerException {
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            scheduler = schedulerFactory.getScheduler();
            // 为了方便直接创建后启用
            scheduler.start();
        }
    
        // 使用同步块确保线程安全
        public static Scheduler getScheduler() {
            if (scheduler == null) {
                synchronized (SchedulerManager.class) {
                    if (scheduler == null) {  // 双重检查
                        try {
                            initScheduler();
                        } catch (SchedulerException e) {
                            // 处理异常或抛出自定义异常
                            e.printStackTrace();
                        }
                    }
                }
            }
            return scheduler;
        }
        
        // 启动 scheduler 
        public static void start() {
            try {
                if (!scheduler.isStarted()) {
                    scheduler.start();
                }
            } catch (SchedulerException e) {
                // 处理异常或抛出自定义异常
                e.printStackTrace();
            }
        }
    
        
        // 暂停任务/删除任务
        public static void stopTask(String jobKey) {
            try {
                Scheduler scheduler = SchedulerManager.getScheduler();
                JobKey key = new JobKey(jobKey, jobKey);
                JobDetail jobDetail = scheduler.getJobDetail(key);
                if (jobDetail != null) {
                    // 获取JobDataMap
                    JobDataMap dataMap = jobDetail.getJobDataMap();
                    dataMap.put("ok", false);
                    // 暂停任务
                    scheduler.pauseJob(key);
                    // 或者删除当前任务
                    // scheduler.deleteJob(key);
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    
        // 恢复任务
        public static int startTask(String jobKey) {
            int o = 0;
            try {
                Scheduler scheduler = SchedulerManager.getScheduler();
                JobKey key = new JobKey(jobKey, jobKey);
                JobDetail jobDetail = scheduler.getJobDetail(key);
                if (jobDetail != null) {
                    // 获取JobDataMap
                    JobDataMap dataMap = jobDetail.getJobDataMap();
                    dataMap.put("ok", true);
                    // 恢复任务
                    scheduler.resumeJob(key);
                    o = 1;
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
            }finally {
                return o;
            }
        }
    
    
         /**
          * 停止所有任务
         */
         public static void stopAllTask() {
            try {
                Scheduler scheduler = context.getScheduler();
                try {
                    // 停止调度器
                    scheduler.shutdown();
                } catch (SchedulerException e) {
                    logger.error("停止调度器时出错", e);
                    throw new JobExecutionException("停止调度器时出错", e);
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
         }
    
    }
  3. 添加cron执行任务类

    java 复制代码
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @Component
    @Slf4j
    @Service
    public class CronThread implements Job {
    
        private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
    
        // 详情id
        String detailId = "";
        // 启用/停用(双重保险)
        boolean ok = true;
        // 设备id
        int facilityId = -1;
    
    
        public void setOK(boolean ok) {
            this.ok = ok;
        }
    
    
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            try {
                JobDataMap dataMap = context.getJobDetail().getJobDataMap();
                // 获取参数,注意数据类型
                this.ok = dataMap.getBoolean("ok");
                if (ok){
                    this.detailId = dataMap.getString("detailId");
                    this.facilityId = dataMap.getInt("facilityId");
                    logger.info("任务执行: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "。key=" + context.getJobDetail().getKey());
                    frameSave();
                }
            } catch (Exception e) {
                logger.error("执行任务异常,内容", e);
                logger.info("停止任务:{}",context.getJobDetail().getKey());
                Scheduler scheduler = context.getScheduler();
                try {
                    // 暂停当前任务
    //                scheduler.pauseJob(context.getJobDetail().getKey());
                    // 或者删除当前任务
                    scheduler.deleteJob(context.getJobDetail().getKey());
                } catch (SchedulerException s) {
                    logger.error("暂停或删除任务时出错", s);
                    throw new JobExecutionException("暂停或删除任务时出错", s);
                }
            }
        }
    
    
        public void frameSave() {
            try {
                logger.info("执行任务");
            } catch (Exception e) {
                logger.error("执行异常,内容: ", e);
            }
        }
    }
  4. 启动/使用 方式

    java 复制代码
        // 启动全部
        public void startAllTasks(List<Map<String,Object>> mapList){
            // 获取scheduler
            Scheduler scheduler = SchedulerManager.getScheduler();
            for (Map<String, Object> map : mapList) {
                try {
                    // 像任务执行类传入参数
                    JobDataMap jobDataMap = new JobDataMap();
                    jobDataMap.put("detailId", map.get("detailId").toString());
                    jobDataMap.put("facilityId", (int) map.get("detailId"));
                    jobDataMap.put("ok", true);
                    // 任务唯一标识 根据情况来定,后续停止或启用单个的时候需要用到该key值
                    String key = map.get("detailId").toString() + "-" + map.get("facilityId").toString();
                    //    上面创建的  cron 执行任务类(CronThread.class)
                    JobDetail jobDetail = JobBuilder.newJob(CronThread.class)
                            .withIdentity(key, key)
                            .setJobData(jobDataMap)
                            .build();
    
                    Trigger trigger = TriggerBuilder.newTrigger()
                            .withIdentity(key, key)
                            .withSchedule(CronScheduleBuilder.cronSchedule(map.get("cronStr").toString()))//cron表达式
                            .build();
                    // 添加任务 到时间后会自动调用(在上面获取scheduler时里面有启动的操作)
                    scheduler.scheduleJob(jobDetail, trigger);
                } catch (Exception e){
                    e.printStackTrace();
                    logger.error("启动抽帧任务报错:: ", e);
                }
            }
        }
    
        // 停止单个任务
        public void stopOneTask(String detailId,int facilityId){
            // 任务唯一标识
            String key = detailId + "-" + facilityId;
            SchedulerManager.stopTask(key);
        }
    
        // 启动单个任务
        public int startOneTask(String detailId,int facilityId,String cronStr){
            // 任务唯一标识
            String key = detailId + "-" + facilityId;
            int i = SchedulerManager.startTask(detailId + "-" + facilityId);
            if (i == 0) {
                // 该任务已被删除 重新添加
                try {
                    // 可以将下面代码封装成一个方法,否则会和上面启动全部任务的操作代码重复
                    JobKey jobKey = new JobKey(key, key);
                    Scheduler scheduler = SchedulerManager.getScheduler();
                    if (scheduler.checkExists(jobKey)) {
                        return 1;
                    }
                    JobDataMap jobDataMap = new JobDataMap();
                    jobDataMap.put("detailId", detailId);
                    jobDataMap.put("facilityId", facilityId);
                    jobDataMap.put("ok", true);
                    JobDetail jobDetail = JobBuilder.newJob(CronThread.class)
                            .withIdentity(key, key)
                            .setJobData(jobDataMap)
                            .build();
                    Trigger trigger = TriggerBuilder.newTrigger()
                            .withIdentity(key, key)
                            .withSchedule(CronScheduleBuilder.cronSchedule(cronStr))
                            .build();
    
                    scheduler.scheduleJob(jobDetail, trigger);
                    return 1;
                } catch (SchedulerException e) {
                    // 处理调度器异常
                    e.printStackTrace();
                    logger.error("One Scheduler exception: ", e);
                    return 0;
                }
            }
            return 0;
        }
相关推荐
计算机学姐几秒前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
小筱在线6 分钟前
SpringCloud微服务实现服务熔断的实践指南
java·spring cloud·微服务
luoluoal11 分钟前
java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)
java·vue.js·spring boot
ChinaRainbowSea16 分钟前
十三,Spring Boot 中注入 Servlet,Filter,Listener
java·spring boot·spring·servlet·web
Crossoads18 分钟前
【数据结构】排序算法---桶排序
c语言·开发语言·数据结构·算法·排序算法
小游鱼KF19 分钟前
Spring学习前置知识
java·学习·spring
2的n次方_21 分钟前
掌握Spring Boot数据库集成:用JPA和Hibernate构建高效数据交互与版本控制
数据库·spring boot·hibernate
扎克begod23 分钟前
JAVA并发编程系列(9)CyclicBarrier循环屏障原理分析
java·开发语言·python
青灯文案124 分钟前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
code bean31 分钟前
【C#基础】函数传参大总结
服务器·开发语言·c#