【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

猜你喜欢

转载自www.cnblogs.com/huashengweilong/p/11430701.html