Jfinal quartz动态的增、删、暂停、恢复job

得益于quartzjfinal-ext插件可以很方便的在jfinal中配置定时任务,方法如下:

  1. 在pom.xml中增加依赖:
     <dependency>
         <groupId>com.jfinal</groupId>
         <artifactId>jfinal-ext</artifactId>
         <version>3.1.4</version>
     </dependency>
     <dependency>
         <groupId>org.quartz-scheduler</groupId>
         <artifactId>quartz</artifactId>
         <version>2.2.2</version>
     </dependency>
    

  1. 在jfinal中配置quartz插件:
     @Override
         public void configPlugin(Plugins me) {
             QuartzPlugin quartzPlugin = new QuartzPlugin("job.properties");
             me.add(quartzPlugin);
     }
    

    }

  2. 集成编写定时任务类:
     public class GroupVersionJo implements Job{
                 private static final Logger logger = Logger.getLogger(GroupVersionJob.class);
    
         @Override
         public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
             addVersionForAllGroup();
         }
     }
    
  3. 增加job.properties配置文件:
     #每天早晨六点定时生成版本库
     a.job=com.meilishuo.autotest.agile.quartz.GroupVersionJob
     a.cron=0 0 6 * * ?
     a.enable=true
    
     #提测单的获取,每分钟一次
     b.job=com.meilishuo.autotest.agile.quartz.ProductCardJob
     b.cron=0 */1 * * * ?
     b.enable=true
    
  4. 完事,:)

但是有个缺点,就是定时任务必须事先定义好,如果我们想动态的增加,删除,暂停,恢复,暂时做不到。其实实现这些功能也很简单,改写一下QuartzPlugin插件的内容。

QuartzPlugin这个对象中维护这一个Scheduler对象,只要能获取到这个对象,我们就能对quartz中所有的job进行修改;源插件中Scheduler对象是私有的,并且没有提供get方法,我们可以修改一下。
1. 如下面的源码,增加了get、set方法,增加了一个addJobWhenRun方法:

    package com.meilishuo.autotest.agile.quartz;

    import com.google.common.base.Throwables;
    import com.google.common.collect.Maps;
    import com.jfinal.ext.kit.Reflect;
    import com.jfinal.ext.kit.ResourceKit;
    import com.jfinal.kit.StrKit;
    import com.jfinal.log.Logger;
    import com.jfinal.plugin.IPlugin;
    import org.quartz.*;
    import org.quartz.impl.StdSchedulerFactory;

    import java.util.Date;
    import java.util.Map;
    import java.util.Set;

    /**
     * Created by Xuemeng Wang on 16-4-20.
     */
    public class MyQuartzPlugin implements IPlugin {
        public static final String VERSION_1 = "1";
        private static final String JOB = "job";
        private final Logger logger = Logger.getLogger(getClass());
        private Map<Job, String> jobs = Maps.newLinkedHashMap();
        private String version;
        private SchedulerFactory sf;
        private Scheduler scheduler;
        private String jobConfig;
        private String confConfig;
        private Map<String, String> jobProp;

        public MyQuartzPlugin(String jobConfig, String confConfig) {
            this.jobConfig = jobConfig;
            this.confConfig = confConfig;
        }

        public MyQuartzPlugin(String jobConfig) {
            this.jobConfig = jobConfig;
        }

        public MyQuartzPlugin() {
        }

        public MyQuartzPlugin add(String jobCronExp, Job job) {
            jobs.put(job, jobCronExp);
            return this;
        }

        @Override
        public boolean start() {
            loadJobsFromProperties();
            startJobs();
            return true;
        }

        private void startJobs() {
            //没有修改,请去阅读源码
        }

        public void loadJobsFromProperties() {
            //没有修改,请去阅读源码
        }

        /**
         * added by xuemeng wang,动态的增加一个job,这部分代码就是上面startJobs大部分的代码
         * @param job
         * @param cronExp
         */
        public void addJobWhenRun(Job job, String cronExp) {
            String jobClassName = job.getClass().getName();
            String jobCronExp = cronExp;
            JobDetail jobDetail;
            CronTrigger trigger;
            //JobDetail and CornTrigger are classes in 1.x version,but are interfaces in 2.X version.
            if (VERSION_1.equals(version)) {
                jobDetail = Reflect.on("org.quartz.JobDetail").create(jobClassName, jobClassName, job.getClass()).get();
                trigger = Reflect.on("org.quartz.CronTrigger").create(jobClassName, jobClassName, jobCronExp).get();
            } else {
                jobDetail = Reflect.on("org.quartz.JobBuilder").call("newJob", job.getClass()).call("withIdentity", jobClassName, jobClassName)
                .call("build").get();
                Object temp = Reflect.on("org.quartz.TriggerBuilder").call("newTrigger").get();
                temp = Reflect.on(temp).call("withIdentity", jobClassName, jobClassName).get();
                temp = Reflect.on(temp).call("withSchedule",
                Reflect.on("org.quartz.CronScheduleBuilder").call("cronSchedule", jobCronExp).get())
                .get();
                trigger = Reflect.on(temp).call("build").get();
            }
            logger.info("jobkey ---> " + jobDetail.getKey()); //这里获取的jobkey很重要,后续删除、暂停、恢复都需要这个jobkey,可以将jobkey维护到db中,方便集中管理。  
            Date ft = Reflect.on(scheduler).call("scheduleJob", jobDetail, trigger).get();
            logger.debug(Reflect.on(jobDetail).call("getKey") + " has been scheduled to run at: " + ft + " " +
            "and repeat based on expression: " + Reflect.on(trigger).call("getCronExpression"));
        }

        public MyQuartzPlugin version(String version) {
            this.version = version;
            return this;
        }
        public MyQuartzPlugin confConfig(String confConfig) {
            this.confConfig = confConfig;
            return this;
        }

        public MyQuartzPlugin jobConfig(String jobConfig) {
            this.jobConfig = jobConfig;
            return this;
        }
        //为Scheduler对象增加一个get方法,让其在外部可以访问
        public Scheduler getScheduler() {
            return scheduler;
        }

}
  1. jfinal在configPlugin方法中,会new一个QuartzPlugin对象,注册到jfinal中。但是我没有找到从Jfinal框架再获取QuartzPlugin对象的方法,因此,我把MyQuartzPlugin对象设置成全局变量,用单例模式保证其只有一个实例。
     /**
      * Created by Xuemeng Wang on 16-4-20.
      */
     public class JobHolder {
         private static MyQuartzPlugin myQuartzPlugin;
    
         private JobHolder() {}
    
         public static MyQuartzPlugin getInstance(String configFileName) {
             if(null == myQuartzPlugin) {
                 myQuartzPlugin = new MyQuartzPlugin(configFileName);
             }
             return myQuartzPlugin;
         }
     }
    
  2. 在Jfinal中注册MyQuartzPlugin对象:
     public void configPlugin(Plugins me)  {
             MyQuartzPlugin myQuartzPlugin = JobHolder.getInstance("job.properties");        
             me.add(myQuartzPlugin);  
    

    }

  3. jfinal启动后,会把配置文件中的定时任务跑起来,增加、删除、暂停、恢复的方法如下:
      MyQuartzPlugin myQuartzPlugin = JobHolder.getInstance(("job.properties"));
      //暂停job
       myQuartzPlugin.getScheduler().pauseJob(new JobKey("com.meilishuo.autotest.agile.quartz.UserSyncJob", "com.meilishuo.autotest.agile.quartz.UserSyncJob"));
         //恢复job
         myQuartzPlugin.getScheduler().resumeJob(new JobKey("com.meilishuo.autotest.agile.quartz.UserSyncJob", "com.meilishuo.autotest.agile.quartz.UserSyncJob"));
         //删除job
         result = myQuartzPlugin.getScheduler().deleteJob(new JobKey("com.meilishuo.autotest.agile.quartz.UserSyncJob", "com.meilishuo.autotest.agile.quartz.UserSyncJob"));
         //增加job
     MyQuartzPlugin myQuartzPlugin = JobHolder.getInstance("job.properties");
     Job job = new UserSyncJob();
     myQuartzPlugin.addJobWhenRun(job, "0 */1 * * * ?");
    
  4. JobKey相当于任务的唯一id,Scheduler通过jobkey来管理job,JobKey对象有两个最重要的属性,namegroup,这两个属性唯一确定一个job。
     //获取scheduler中所有的jobkey
     Set<JobKey> jobKeys = myQuartzPlugin.getScheduler().getJobKeys(GroupMatcher.anyJobGroup());
    

发表评论

电子邮件地址不会被公开。 必填项已用*标注

(Spamcheck Enabled)