侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

SpringMVC java 使用quartz实现灵活的定时任务

2022-06-30 星期四 / 0 评论 / 0 点赞 / 50 阅读 / 11496 字

引言最近项目中有这样一个业务,相信大家也经常遇到。就是用户通过前端设置了某年某月某日的定时任务,后台接收并且定时执行。这个定时可以通过前端UI改变,或者删除,所以后端也需要做三个事,1-添加定时任务,

引言

最近项目中有这样一个业务,相信大家也经常遇到。就是用户通过前端设置了某年某月某日的定时任务,后台接收并且定时执行。这个定时可以通过前端UI改变,或者删除,所以后端也需要做三个事,1-添加定时任务,2-修改定时任务时间,3-删除定时任务。

Spring的定时任务

Spring通过@Scheduled注解为定时任务,cron表达式里写执行的时机,确实能够定时执行某个方法,但是却没办法灵活的管理任务的添加,改变,丢弃。所以不满足我们的需求。

@Scheduled(cron="0/10 * *  * * ? ")   //每10秒执行一次    

自定义org.quartz.Scheduler.Scheduler实现灵活定时任务管理

1. 建一个Scheduler的包装类,提供单例实例的获取

这里生成一个Scheduler的包装类,并且只返回自身的单例。并通过getScheduler()获取到Scheduler的实例,这里也保证他它是单例。


SchedulerController.java

public class SchedulerController {    private static SchedulerController own;    private Scheduler myScheduler;    HashMap<String, TriggerKey> triggers = new HashMap<String, TriggerKey>();    HashMap<String, JobKey> jobs = new HashMap<String, JobKey>();        private SchedulerController() {    }        // 单例模式 获取包装类实例    public static SchedulerController getInstance() {        return own = Optional.ofNullable(own).orElse(new SchedulerController());    }    // 单例模式 生成Scheduler    private Scheduler getScheduler() {        try {            myScheduler = Optional.ofNullable(myScheduler).orElse(new StdSchedulerFactory().getScheduler());        } catch (SchedulerException e) {            throw new RuntimeException(e);        }        return myScheduler;    }}

2.新建任务注册到Scheduler并启动

通过addJob()方法添加任务,接收的是一个Job类的实现类。startScheduler()启动任务。其中添加任务分为几步。

  • 生成一个JobDetail类的实例,封装你的任务细节。包含了一个JobKey描述任务名跟任务组。
  • 生成一个Trigger触发器的实例,封装你的定时时间。包含了一个TriggerKey描述任务名跟任务组。
  • 把JobDetail跟Trigger注册到你的Scheduler中。

SchedulerController.java

public Scheduler addJob(ScheduleJob job, String cron) {    Scheduler s = getScheduler();        // jobDetail生成    JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());    jobs.put(job.getJobName(), jobKey);    JobDetail jobDetail = JobBuilder.newJob(job.getClass()).withIdentity(jobKey).build();        // trigger生成    TriggerKey triggerKey = new TriggerKey(job.getJobName(), job.getTriggerGroup());    triggers.put(job.getJobName(), triggerKey);    Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)            .withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();        try {        // 添加jobDetail跟trigger        s.scheduleJob(jobDetail, trigger);    } catch (SchedulerException e) {        throw new RuntimeException(e);    }    return s;}public void startScheduler() {    try {        if (myScheduler != null && !myScheduler.isShutdown()) {            // 启动任务            myScheduler.start();        }    } catch (SchedulerException e) {        throw new RuntimeException(e);    }}

ScheduleJob.java

@Datapublic class ScheduleJob implements Job {    private String jobName;    private String jobGroup;    private String triggerGroup;        public ScheduleJob() {            }        public ScheduleJob(String jobName) {        this.jobName = jobName;    }        @Override    public void execute(JobExecutionContext context) throws JobExecutionException {        // 实际执行内容        System.out.println("test");    }}

3.修改任务时间,删除任务

上面说了任务时间是封装到Trigger触发器的,所以修改任务的核心代码在于CronTriggerImpl#setCronExpression(),来重设时间,再通过Scheduler#rescheduleJob()来重置。

删除任务则是Scheduler#unscheduleJob()跟Scheduler#deleteJob()。


SchedulerController.java

public void modifyJobTime(String jobName, String cronExpression) {    try {        if (myScheduler == null) {            return;        }                TriggerKey triggerKey = getTriggerKeyByName(jobName);        CronTriggerImpl trigger = (CronTriggerImpl) myScheduler.getTrigger(triggerKey);        if (trigger == null) {            return;        }                String oldTime = trigger.getCronExpression();                if (!oldTime.equalsIgnoreCase(cronExpression)) {            try {                trigger.setCronExpression(cronExpression);            } catch (ParseException e) {                throw new RuntimeException(e);            }            myScheduler.rescheduleJob(triggerKey, trigger);        }    } catch (SchedulerException e) {        throw new RuntimeException(e);    }}public void removeJob(String jobName) {    try {        myScheduler.pauseTrigger(getTriggerKeyByName(jobName));        myScheduler.unscheduleJob(getTriggerKeyByName(jobName));        myScheduler.deleteJob(getJobByName(jobName));    } catch (SchedulerException e) {        throw new RuntimeException(e);    }}private TriggerKey getTriggerKeyByName(String jobName) {    if (!triggers.containsKey(jobName)) {        throw new RuntimeException("triggerNotExist");    }    return triggers.get(jobName);}private JobKey getJobByName(String jobName) {    if (!jobs.containsKey(jobName)) {        throw new RuntimeException("jobNotExist");    }        return jobs.get(jobName);}

4.测试一下

先每隔一秒实行job,然后改为两秒,最后删除任务。

SchedulerController sc = SchedulerController.getInstance();sc.addJob(new ScheduleJob("Test"), "*/1 * * * * ?");sc.startScheduler();try {	Thread.sleep(1000 * 5);} catch (InterruptedException e) {	e.printStackTrace();}sc.modifyJobTime("Test", "*/2 * * * * ?");sc.removeJob("Test");

总结

自定义定时任务比较复杂,但是学会了后能够灵活的处理定时任务。

.
.

广告 广告

评论区