quartz动态新增、修改、删除

前言:最近项目中要开发一个可以让用户自己定义推送时间,推送内容的类似订阅的功能。想了想实现方式,task、quartz、Thread。最终还是用了比较专业的quartz。quartz实现了任务、触发器、调度器的分离,符合java开发的分离原则,很容易上手。废话不说直接贴代码了。

1.定义job导出类(实现job接口,所有的任务都是用这个类,稍后会解释)

    public class MyQuartzJob implements Job {
        private static Logger logger = LoggerFactory.getLogger(MyQuartzJob.class);

        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // TODO Auto-generated method stub
            System.out.println("任务成功运行,时间为:===" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // JobDataMap jdm = context.getMergedJobDataMap();

            JobDetailImpl jdi = (JobDetailImpl) context.getJobDetail();

            JobKey jk = jdi.getKey();

            String jobName = jk.getName();
            String jobGroup = jk.getGroup();

            Trigger trigger = context.getTrigger();
            TriggerKey triggerKey = trigger.getKey();

            String triggerName = triggerKey.getName();
            String triggerGroup = triggerKey.getGroup();

            if (jobName.equals("我的cron任务1")) {
                try {
                    QuartzManager.modifyJobTime(triggerKey, "0 0/3 * * * ?");
                } catch (SchedulerException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println("当前执行的job是:" + jobName + ";job的组名是:" + jobGroup + ";trigger名称是:" + triggerName
                    + ";trigger的组名是:" + triggerGroup + ";下次执行时间为:"
                    + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(context.getNextFireTime()));
            System.out.println();
            // JobDetailImpl scheduleJob = (JobDetailImpl)
            // context.getMergedJobDataMap().get("scheduleJob");
            // System.out.println("任务名称 = [" + scheduleJob.getName() + "]");

            /*
             *从jobDataMap中取得推送相关的额外信息; 
             * */
            JobDataMap dataMap = context.getMergedJobDataMap();
            // userId
            String userId = (String) dataMap.get("userId");
            //
            String messageTypes = (String) dataMap.get("messageTypes");

            //下边的这里是项目的业务   就不贴出来了
            // 根据用户id查询该用户定义的
            // PushAlarmService alarmService = SpringUtils.getBean(PushAlarmService.class);
            // alarmService.selByUserId(Integer.valueOf(userId));

        }
    }

2.定义一个定时器的管理类:专门负责定时器的新增、修改、删除、启动、结束等。

代码里面的注释写的很详细了,自己看一下就知道是什么意思。

    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.SchedulerException;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.SimpleTrigger;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.TriggerKey;
    import org.quartz.impl.StdSchedulerFactory;

    public class QuartzManager {
        // private static final String JOB_GROUP_NAME = "SDJK_APP_JOBGROUP_NAME";
        /// private static String TRIGGER_GROUP_NAME = "SDJK_APP_TRIGGERGROUP_NAME";
        public static StdSchedulerFactory sf = new StdSchedulerFactory();
        // public static StdScheduler ss = (StdScheduler) SpringUtils.getBean("schedulerFactoryBean");

        /**
         * 
         * @Title:
         * @Description: 创建SimpleTrigger定时器,startnow,run forever
         *
         * @param jobKey
         * @param triggerKey
         * @param cls
         * @param repeatIntevalTime
         * @throws SchedulerException
         */
        public static void addJob(JobKey jobKey, TriggerKey triggerKey, Class<? extends Job> cls, int repeatIntevalTime,
                JobDataMap jobDataMap) throws SchedulerException {

            Scheduler sched = sf.getScheduler();

            JobDetail jd = JobBuilder.newJob(cls).withIdentity(jobKey).setJobData(jobDataMap).build();// jobDetail

            SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
                    .withSchedule(
                            SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(repeatIntevalTime).repeatForever())
                    .startNow().build();// triggerkey用来标识trigger身份

            sched.scheduleJob(jd, trigger);// 设置调度器

            try {

                if (!sched.isShutdown()) {
                    sched.start();
                }

            } catch (SchedulerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        /**
         * 
         * @Title:
         * @Description: 添加cronTrigger的定时器
         *
         * @param jobKey
         * @param triggerKey
         * @param jobClass
         * @param cron
         * @param JobDataMap
         *            jobDataMap
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static void addJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron,
                JobDataMap jobDataMap) {
            try {
                // 任务名,任务组,任务执行类;可以将自己需要的额外信息添加到jobdatamap中。
                JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).setJobData(jobDataMap).build();

                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();// 触发器

                triggerBuilder.withIdentity(triggerKey);// 触发器名,触发器组

                triggerBuilder.startNow();// 现在执行

                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));// 触发器执行规则

                CronTrigger trigger = (CronTrigger) triggerBuilder.build();// 创建CronTrigger对象

                Scheduler sched = sf.getScheduler();// 创建调度器

                sched.scheduleJob(jobDetail, trigger);// 调度容器设置JobDetail和Trigger

                if (!sched.isShutdown()) {// 启动
                    sched.start();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * 
         * @Title:
         * @Description: 修改cronTrigger定时器
         *
         * @param triggerKey
         *            trigger标识
         * @param cron
         * @throws SchedulerException
         */
        public static void modifyJobTime(TriggerKey triggerKey, String cron) throws SchedulerException {

            Scheduler sched = sf.getScheduler();

            try {
                // TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

                CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);

                if (trigger == null) {
                    return;
                }

                String oldTime = trigger.getCronExpression();

                if (!oldTime.equalsIgnoreCase(cron)) {

                    /** 方式一 :调用 rescheduleJob 开始 */
                    TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();// 触发器

                    triggerBuilder.withIdentity(triggerKey);// 触发器名,触发器组

                    triggerBuilder.startNow();// 立即执行

                    triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));// 触发器时间设定

                    trigger = (CronTrigger) triggerBuilder.build();// 创建Trigger对象

                    sched.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间

                    /** 方式一 :调用 rescheduleJob 结束 */

                    /** 方式二:先删除,然后在创建一个新的Job */
                    // JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                    // Class<? extends Job> jobClass = jobDetail.getJobClass();
                    // removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                    // addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                    /** 方式二 :先删除,然后在创建一个新的Job */
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * 
         * @Title:
         * @Description: 只修改simpleTrigger触发器的触发时间,不更改trigger的triggerKey
         *
         * @param triggerKey
         *            trigger标识
         * @param repeatIntervalTime
         *            重复间隔时长
         * @throws SchedulerException
         */
        public static void modifyJobTime(TriggerKey triggerKey, int repeatIntervalTime) throws SchedulerException {

            Scheduler sched = sf.getScheduler();

            try {

                SimpleTrigger trigger = (SimpleTrigger) sched.getTrigger(triggerKey);

                if (trigger == null) {
                    return;
                }

                long oldTime = trigger.getRepeatInterval();

                if (oldTime != repeatIntervalTime) {

                    /** 方式一 :调用 rescheduleJob 开始 */
                    TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();// 触发器builder

                    triggerBuilder.withIdentity(triggerKey);// 触发器名,触发器组

                    triggerBuilder.withSchedule(SimpleScheduleBuilder.repeatHourlyForever(repeatIntervalTime));// 更新触发器的重复间隔时间

                    triggerBuilder.startNow();// 立即执行

                    trigger = (SimpleTrigger) triggerBuilder.build();// 创建Trigger对象

                    sched.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间

                    /** 方式一 :调用 rescheduleJob 结束 */

                    /** 方式二:先删除,然后在创建一个新的Job */
                    // JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                    // Class<? extends Job> jobClass = jobDetail.getJobClass();
                    // removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                    // addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                    /** 方式二 :先删除,然后在创建一个新的Job */
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * 
         * @Title:
         * @Description: 根据job和trigger删除任务
         *
         * @param jobKey
         * @param triggerKey
         */
        public static void removeJob(JobKey jobKey, TriggerKey triggerKey) {

            try {

                Scheduler sched = sf.getScheduler();

                sched.pauseTrigger(triggerKey);// 停止触发器

                sched.unscheduleJob(triggerKey);// 移除触发器

                sched.deleteJob(jobKey);// 删除任务

            } catch (Exception e) {

                throw new RuntimeException(e);

            }
        }

        /**
         * @Description:启动所有定时任务
         */
        public static void startJobs(Scheduler sched) {
            try {
                sched.start();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * @Description:关闭所有定时任务
         */
        public static void shutdownJobs(Scheduler sched) {
            try {
                if (!sched.isShutdown()) {
                    sched.shutdown();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * 
         * @Title:
         * @Description: 新增或者修改
         *
         * @param jobKey
         * @param triggerKey
         * @param clz
         * @param intervalTime
         * @param jobDataMap
         * @throws SchedulerException
         */
        public static void addOrModify(JobKey jobKey, TriggerKey triggerKey, @SuppressWarnings("rawtypes") Class clz,
                int intervalTime, JobDataMap jobDataMap) throws SchedulerException {

            Scheduler sched = sf.getScheduler();

            if (sched.checkExists(jobKey)) {// 如果存在,则modify一下job和trigger

            }

            if (sched.checkExists(triggerKey)) {// modify修改trigger

                modifyJobTime(triggerKey, intervalTime);

            } else {// add新增

                addJob(jobKey, triggerKey, clz, intervalTime, jobDataMap);

            }

        }
    }

可以看到,每次创建job是都要使用一个实现了job接口的类,这个类就是我们自己实现的job导出类。

3.初始定时任务的初始化类。作用:项目启动时,初始化自己定义的定时器。既然需要项目启动时就加载所有的定时器,那么需要在spring容器加载时一起加载。

    public class InitQuartzJob {

        /**
         * @throws SchedulerException
         * @Description:服务启动时,根据用户定义的推送规则,初始化所有的推送任务。每个用户选择自己的隧道,为每条隧道指定推送的间隔时间。 因此同一个用户可能有多个定时任务。
         */
        public static void init() throws SchedulerException {
            System.out.println("定时器初始化开始==============================");

            JobDataMap dataMap1 = new JobDataMap();
            dataMap1.put("subCode", "sdnanhuan");
            dataMap1.put("messageType", "all");
            JobKey jobKey1 = new JobKey("我的cron任务1", "我的cron任务组名1");
            TriggerKey triggerKey1 = new TriggerKey("我的cron触发器名1", "我的cron触发器组名1");

            JobKey jobKey2 = new JobKey("我的cron任务2", "我的cron任务组名1");// job的名字不能重复
            TriggerKey triggerKey2 = new TriggerKey("我的cron触发器名2", "我的cron触发器组名2");

            QuartzManager.addJob(jobKey1, triggerKey1, MyQuartzJob.class, "0 0/2 * * * ?", null);
            QuartzManager.addJob(jobKey2, triggerKey2, MyQuartzJob.class, "0 0/2 * * * ?", null);


        }
    }

主要的结构就是这样子了。至于其中使用的一些工具类SpringUtils、配置文件什么的,可以参考我之前的文章。

4.最后就是在自己的业务系统里面,调用定时器工具类了。当业务提交后,如果需要创建或者修改定时器,直接在业务层调用工具类就可以了。

暂时先写这些吧。

猜你喜欢

转载自blog.csdn.net/Jatham/article/details/81384454