• 【Java】【51】Quartz定时器


    前言:

    如果是确定了执行时间或者时间间隔的定时任务,可以用注解@Scheduled来处理(【Spring】【2】使用注解@Scheduled执行定时任务 - 花生喂龙 - 博客园 https://www.cnblogs.com/huashengweilong/p/10934471.html

    但是,有的时候我们的任务是动态的。比如,可以在后台添加任意个数任意时间的推送短信任务,任务没有开始之前,可以更改推送时间。这就需要用到Quartz动态添加、修改和删除定时任务时间了

    正文:

    1,pom.xml

    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>  
        <artifactId>spring-context-support</artifactId>  
    </dependency>

    2,查询项目中存在哪些定时任务,可以看到定时任务是否符合期望

    @CrossOrigin(origins = "*")
    @RestController
    public class JobController {
        @Autowired ControlJob controlJob;
        
        //查看定时任务
        @RequestMapping(value = "job/list", method = RequestMethod.GET)
        public List<JobVo> getAllJobs() 
        {    
            return this.controlJob.getAllJobs();
        }
    }

    其中的JobVo

    //我查看三个参数
    private String jobName; //任务名称
    
    private String jobGroup; //任务类型
        
    private String nextFireTime; //下次触发时间

    getAllJobs方法

    @Service
    public class ControlJob {
        protected final Logger logger = LoggerFactory.getLogger(this.getClass());
        @Autowired private Scheduler scheduler;
        
        public List<JobVo> getAllJobs(){
            try {
                List<JobVo> list = new ArrayList<JobVo>();            
                for (String groupName : scheduler.getJobGroupNames()) {         
                    for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
                        JobVo info = new JobVo();
                        info.setJobName(jobKey.getName());
                        info.setJobGroup(jobKey.getGroup());
    
                        List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
                        Date nextFireTime = triggers.get(0).getNextFireTime();
                        info.setNextFireTime(CalendarUtil.DtoS(nextFireTime));
                        list.add(info);
                    }
                }
                
                return list;
            } catch (Exception e) {
                logger.info("getAllJobs error:" + e);
            }
            
            return null;
        }
    }

    3,定时查数据库,并根据查询结果决定是否重新设置定时任务(我觉得也可以后台修改任务后,更改定时器。但是由于当时前端接口代码和后台代码不在一块,和后台同事协商后,约定以数据库为桥梁,各自处理各自的部分)

    import org.quartz.CronScheduleBuilder;
    import org.quartz.CronTrigger;
    import org.quartz.JobBuilder;
    import org.quartz.JobDataMap;
    import org.quartz.JobDetail;
    import org.quartz.JobKey;
    import org.quartz.Scheduler;
    import org.quartz.TriggerBuilder;
    import org.quartz.TriggerKey;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    
    @Service
    public class TriggerMessage {
        protected final Logger logger = LoggerFactory.getLogger(this.getClass());
        
        private static String MESSAGE_GROUP_NAME = "MESSAGE";
        @Autowired private Scheduler scheduler;
        @Autowired PushMessageService pushMessageService;
        
        @Scheduled(fixedRate = 65000) // 每隔1.5分钟查库,并根据查询结果决定是否重新设置定时任务
        public void init(){
            //从数据库中获取所有任务。注意PushMessageVo中的corn字段,格式为"ss mm HH dd MM ? yyyy"
            List<PushMessageVo> jobList = this.pushMessageService.getPushMessageList();
            
            for (PushMessageVo item : jobList) {
                String jobName = item.getMsgCode();
                logger.info("message jobName:"+jobName);
                
                try {
                    TriggerKey triggerKey = TriggerKey.triggerKey(jobName, MESSAGE_GROUP_NAME);
                    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); //判断该定时器是否存在                        
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(item.getCron()); //表达式调度构建器
                                    
                    if (item.getStatus() == 0){ //状态为0,清理定时器
                        if (trigger != null) {
                            logger.info("message job clear");
                            scheduler.pauseTrigger(triggerKey); //停止触发器  
                            scheduler.unscheduleJob(triggerKey); //移除触发器  
                            scheduler.deleteJob(JobKey.jobKey(jobName, MESSAGE_GROUP_NAME)); //删除任务 
                        }
                    } else {
                        if (trigger == null) { //不存在,创建一个
                            logger.info("message job create");
                            trigger = TriggerBuilder.newTrigger()
                                    .withIdentity(jobName, MESSAGE_GROUP_NAME)
                                    .withSchedule(scheduleBuilder)
                                    .build(); //按新的cronExpression表达式构建一个新的trigger
        
                            JobDetail jobDetail = JobBuilder.newJob(PushMessageJob.class).withIdentity(item.getMsgCode(), MESSAGE_GROUP_NAME).build();
                            jobDetail.getJobDataMap().put("job", item);
                            scheduler.scheduleJob(jobDetail, trigger);                 
                        } else { //存在,更新
                            logger.info("message job reset");
                            trigger = trigger.getTriggerBuilder()
                                     .startAt(new Date())
                                     .withIdentity(triggerKey)
                                     .withSchedule(scheduleBuilder).build();
         
                             JobDataMap jobDataMap = trigger.getJobDataMap(); //重新获取JobDataMap,并且更新参数
                             jobDataMap.put("job", item); 
                             scheduler.rescheduleJob(triggerKey, trigger); //按新的trigger重新设置job执行
                        }
                    }
                } catch (Exception e) {
                    logger.info("TriggerMessage error:" + e);
                }
            }
        }
        
    }

    PushMessageJob(执行的具体内容)

    @Configuration  
    @Component
    @EnableScheduling
    @DisallowConcurrentExecution
    public class PushMessageJob implements Job {
        protected final Logger logger = LoggerFactory.getLogger(this.getClass());
        
        public void execute(JobExecutionContext context) throws JobExecutionException {              
            PushMessageVo info = (PushMessageVo) context.getMergedJobDataMap().get("job"); //获取定时器中信息
            String parentCode = info.getMsgCode(); //消息表code
            logger.info("message code:" + parentCode);
            //根据parentCode获取通知消息               
            //获取要推送的成员               
            //推送
        }
    }

    参考博客:

    Quartz定时器 官方文档翻译 - 简书
    https://www.jianshu.com/p/d1feb7f2821e?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    Quartz 2.2 动态添加、修改和删除定时任务 - xlxxcc的专栏 - CSDN博客
    https://blog.csdn.net/xlxxcc/article/details/52115995

    quartz定时任务cron表达式详解 - 懒惰虫 - 博客园
    https://www.cnblogs.com/lazyInsects/p/8075487.html

    springboot整合quartz定时器实现定时任务详解 - 上善若水任方圆 - CSDN博客
    https://blog.csdn.net/qq_28483283/article/details/80623417

    Spring整合Quartz实现动态定时器 - 五指少年 - 博客园
    https://www.cnblogs.com/xrab/p/5850186.html

    Quartz使用总结 - 路边飞 - 博客园
    https://www.cnblogs.com/drift-ice/p/3817269.html

    springboot整合Quartz实现动态配置定时任务 - 牛奋lch - CSDN博客
    https://blog.csdn.net/liuchuanhong1/article/details/60873295

    spring boot整合quartz实现多个定时任务 - 牛奋lch - CSDN博客
    https://blog.csdn.net/liuchuanhong1/article/details/78543574

  • 相关阅读:
    delphi 类型转化
    VCL主要框架
    delphi TFileStream.create
    delphi常用函数过程
    VMT & DMT
    index.jsp报错The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path的解决办法
    the selection cannot be run on any server错误解决方法
    从request获取各种路径总结
    A Java Exception has occurred 和 org/apache/juli/logging/LogFactory错误解决方法
    操作系统第5次实验报告:内存管理
  • 原文地址:https://www.cnblogs.com/huashengweilong/p/11430701.html
Copyright © 2020-2023  润新知