开发VStation过程中,需要实现任务调度,以前用过Quartz,很不错。现在作为插件,集成到Jfinal中。
思路如下:
1、创建QuartzPlugin ,在启动Jfinal是调用。
2、QuartzPlugin中需要调度的Job通过 Job.properties文件定义,支持多个Job定义。通过反射方式,进行调用。
3、每个Job的cron都可设定,且可控制单个Job是否运行
以上实现后,基本可以满足简单的调度工作。
有待优化地方:
1、支持多个scheduler方式
2、支持数据库方式缓存Job内容
------------------------------
代码如下:
/** Quartz Pojo @author 作者 左浩(James )E-mail: 25708164@qq.com @date 创建时间:2016年12月27日 下午6:16:32 @version 1.0 @since @return */ package com.vstation.plugins.quartzPlugin; public class Quartz { private String propFile; private String jobsFile; private boolean isEnableRun; public String getPropFile() { return propFile; } public void setPropFile(String propFile) { this.propFile = propFile; } public String getJobsFile() { return jobsFile; } public void setJobsFile(String jobsFile) { this.jobsFile = jobsFile; } public boolean isEnableRun() { return isEnableRun; } public void setEnableRun(boolean isEnableRun) { this.isEnableRun = isEnableRun; } }
/** Quartz Job Pojo @author 作者 左浩(James) E-mail: 25708164@qq.com @date 创建时间:2016年12月27日 下午6:04:33 @version 1.0 @since @return */ package com.vstation.plugins.quartzPlugin; public class QuartzJob { private String className; private String cron; private String jobName; private String groupName; private boolean run; public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getCron() { return cron; } public void setCron(String cron) { this.cron = cron; } public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public boolean isRun() { return run; } public void setRun(boolean run) { this.run = run; } }
/** Quartz Plugins @author 作者 左浩(James) E-mail: 25708164@qq.com @date 创建时间:2016年12月27日 下午5:42:46 @version 1.0 @since @return */ package com.vstation.plugins.quartzPlugin; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.quartz.CronTrigger; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SchedulerMetaData; import org.quartz.impl.StdSchedulerFactory; import com.jfinal.kit.Prop; import com.jfinal.kit.PropKit; import com.jfinal.plugin.IPlugin; import com.vstation.controller.UserController; public class QuartzPlugin implements IPlugin { private static Logger log = Logger.getLogger(UserController.class); // private String propertiesFile = "quartz.properties"; private String jobsFile = "jobs.properties"; // private boolean isEnableRun = false; private List<String> jobNameList = new ArrayList<String>(); //Job 名称清单 private Map<String, QuartzJob> JobsMap = new HashMap<String, QuartzJob>(); //Job 对象Map private SchedulerFactory sf; private Scheduler sched; public QuartzPlugin(Quartz q) { // this.propertiesFile = q.getPropFile(); this.jobsFile = q.getJobsFile(); // this.isEnableRun = q.isEnableRun(); init(); } @SuppressWarnings("unchecked") @Override public boolean start() { // TODO Auto-generated method stub log.info("---------- QuartzPlugin start begin--------------"); try { sf = new StdSchedulerFactory(); sched = sf.getScheduler(); for(int i=0, length = jobNameList.size(); i<length;i++){ String jobName = jobNameList.get(i); QuartzJob jobObj = JobsMap.get( jobName); boolean isRun = jobObj.isRun(); if(isRun){ Class<? extends Job> jobClass1; jobClass1 = (Class<? extends Job>) Class.forName(jobObj .getClassName()); JobDetail job = newJob(jobClass1) .withIdentity(jobName, jobObj.getGroupName()).build(); CronTrigger trigger = newTrigger() .withIdentity("trigger1", jobObj.getGroupName()) .withSchedule(cronSchedule(jobObj.getCron())).build(); sched.scheduleJob(job, trigger); log.info("add "+jobName +" to quartz schedule "); }else{ log.info(jobName +" run is "+ isRun); } } sched.start(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e.toString()); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e.toString()); } log.info("---------- QuartzPlugin start end --------------"); return true; } @Override public boolean stop() { log.info("---------- QuartzPlugin stop begin --------------"); try { sched.shutdown(true); SchedulerMetaData metaData = sched.getMetaData(); log.info("Executed " + metaData.getNumberOfJobsExecuted()+ " jobs."); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e.toString()); } log.info("---------- QuartzPlugin stop end --------------"); return false; } private boolean init() { log.info("----------init Quartz Jobs begin -------------"); boolean result = false; // Prop prop = PropKit.use(propertiesFile); Prop jobProp = PropKit.use(jobsFile); Enumeration<Object> e = jobProp.getProperties().keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); if (key.indexOf("job.name")==0) { String jobName = jobProp.get(key); jobNameList.add(jobName); QuartzJob job = new QuartzJob(); job.setClassName(jobProp.get(jobName + ".class")); job.setCron(jobProp.get(jobName + ".cron")); job.setGroupName(jobProp.get(jobName + ".group")); job.setRun(jobProp.getBoolean(jobName+".run")); JobsMap.put(jobName, job); log.info("job.name."+jobName+" put to map"); }else{ continue; } } log.info("----------init Quartz Jobs end -------------"); return result; } }
Jfinal Config 中调用代码 /**---------Quartz 插件-----------**/ Quartz q = new Quartz(); q.setJobsFile("jobs.properties"); QuartzPlugin quartzPlugin = new QuartzPlugin(q); me.add(quartzPlugin);
quartz.properties 文件
org.quartz.scheduler.instanceName=VstationScheduler org.quartz.scheduler.instanceId=AUTO org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 20 org.quartz.threadPool.threadPriority = 9 org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore #org.quartz.jobStore.class=org.quartz.simpl.JDBCJobStore org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
jobs.properties 文件
####quartz 配置类 ### #author 左浩(James) #Email 25708164@qq.com #Date 2016-12-26 #规则说明: #1、以job.name 开头,多个job.name 表示有多个任务 #2、以job.name 的value 作为每个任务的后续配置key #--------------信息发送Jobs begin----------------# job.name.msg=msgSender msgSender.class=com.vstation.quartz.jobs.msgSendJob msgSender.run=false msgSender.group=msgsender msgSender.cron=* * * * * #--------------信息发送Jobs end ----------------# #--------------日志收集Jobs begin----------------# job.name.log=LogWriter LogWriter.class=com.vstation.jobs.LogJob LogWriter.run=true LogWrite.group=logwrite LogWriter.cron=0/5 * * * * ? #--------------日志收集Jobs end ----------------#