开发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 ----------------#
代码如下