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;
        }
相关推荐
为了更好的明天而战18 分钟前
Java 中的 ArrayList 和 LinkedList 区别详解(源码级理解)
java·开发语言
JosieBook42 分钟前
【Java编程动手学】Java中的数组与集合
java·开发语言·python
qq_589568101 小时前
element-plus按需自动导入的配置 以及icon图标不显示的问题解决
开发语言·javascript·ecmascript
N_NAN_N1 小时前
类图+案例+代码详解:软件设计模式----单例模式
java·单例模式·设计模式
lsx2024061 小时前
SQLite Select 语句详解
开发语言
weixin_399380691 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
Dovis(誓平步青云)1 小时前
基于探索C++特殊容器类型:容器适配器+底层实现原理
开发语言·c++·queue·适配器·stack
lang201509281 小时前
Reactor ConnectableFlux支持多订阅者
java·网络
R-sz1 小时前
java流式计算 获取全量树形数据,非懒加载树,递归找儿
java·开发语言·windows
Ramos丶1 小时前
【ABAP】 从无到有 新建一个Webdynpro程序
java·前端·javascript