随着需求的增加,现在要定时启动一个调度和计划任务,原先写的QuartzPlugin,是持久化保存到数据库中的,从数据库中读取任务并执行。要是添加一个每天循环任务,就要在代码里写一次开始任务的代码,执行后,再注释掉,最后重启项目。否则会因为启动同name,同group的任务而报错
org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'group_test_1.job_test_1', because one already exists with this identification.
原先JFinal-ext中是通过配置文件,定时循环运行的,两者结合不就是我要的吗?
思路清晰,持久化依旧,再在QuartzPlugin 中增加读取配置文件后生成调度任务,当然,这个也会保存到数据库中的,所以还要在停止的时候,终止和删除相应调度任务,否则下次启动就会报冲突了。
修改的QuartzPlugin 依旧参考了jfinal-ext,做了一些修改,原先会依赖com.google.guava:guava这个jar,因为本人有点强迫症,不喜欢jar包太多,所以能不加就不加了。
import com.jfinal.plugin.IPlugin;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import sedion.net.gppz.quartz.QuartzFactory;import sedion.net.gppz.utils.PropertiesUtil;import java.util.*;import static org.quartz.JobBuilder.newJob;import static org.quartz.TriggerBuilder.newTrigger;/** * Quartz插件 * * @author WWF */public class QuartzPlugin implements IPlugin { private static final String JOB = "job"; /** * 默认配置文件 **/ private String config = "quartz.properties"; private String job_config = "jobs.properties"; private Mapjobs = new LinkedHashMap<>(); private Map jobProp; public QuartzPlugin() { } public QuartzPlugin(String config) { this.config = config; } public QuartzPlugin(String config, String job_config) { this.config = config; this.job_config = job_config; } @Override public boolean start() { try { //加载配置文件 Properties props = PropertiesUtil.loadPropertyFile(config); //实例化 QuartzFactory.sf = new StdSchedulerFactory(props); //获取Scheduler Scheduler sched = QuartzFactory.sf.getScheduler(); //从配置文件中加载定时任务 loadJobsFromProperties(); if (jobs.size() > 0) { Set > set = jobs.entrySet(); for (Map.Entry entry : set) { Job job = entry.getKey(); String jobClassName = job.getClass().getName(); String jobCronExp = entry.getValue(); JobDetail jobDetail = newJob(job.getClass()) .withIdentity(jobClassName, jobClassName) .requestRecovery() .build(); CronTrigger trigger = newTrigger() .withIdentity(jobClassName, jobClassName) .withSchedule(CronScheduleBuilder.cronSchedule(jobCronExp)) .build(); sched.scheduleJob(jobDetail, trigger); } } sched.start(); return true; } catch (Exception e) { e.printStackTrace(); } return false; } @Override public boolean stop() { try { //从配置文件中加载定时任务 loadJobsFromProperties(); Scheduler sched = QuartzFactory.sf.getScheduler(); if (jobs.size() > 0) { Set > set = jobs.entrySet(); for (Map.Entry entry : set) { Job job = entry.getKey(); String jobClassName = job.getClass().getName(); TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobClassName); Trigger trigger = sched.getTrigger(triggerKey); if (trigger != null) { sched.pauseTrigger(triggerKey);// 停止触发器 sched.unscheduleJob(triggerKey);// 移除触发器 sched.deleteJob(trigger.getJobKey());// 删除任务 } } } sched.shutdown(); QuartzFactory.sf = null; return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 从配置文件中加载定时任务 */ private void loadJobsFromProperties() { //清空任务 jobs.clear(); Properties properties = PropertiesUtil.loadPropertyFile(job_config); jobProp = new HashMap<>((Map) properties); Set > entries = jobProp.entrySet(); for (Map.Entry entry : entries) { String key = entry.getKey(); if (!key.endsWith(JOB) || !isEnableJob(key)) { continue; } String jobClassName = jobProp.get(key) + ""; String jobCronExp = jobProp.get(cronKey(key)) + ""; try { Class c = Class.forName(jobClassName); jobs.put((Job) c.newInstance(), jobCronExp); } catch (Exception e) { e.printStackTrace(); } } } /** * 获得cron表达式 * @param key * @return */ private String cronKey(String key) { return key.substring(0, key.lastIndexOf(".") + 1) + "cron"; } /** * 是否开启 * @param key * @return */ private boolean isEnableJob(String key) { String enableKey = key.substring(0, key.indexOf(".") + 1) + "enable"; Object enable = jobProp.get(enableKey); if (enable != null && "true".equalsIgnoreCase((enable + "").trim())) { return true; } return false; }}
在看jfinal-ext源码的时候,有个疑问,
看介绍,job的配置文件是
#JobAa.job=test.com.jfinal.plugin.quzrtz.JobAa.cron=*/5 * * * * ?a.enable=true
但是在代码中,转化为map后,获取相应的key的处理是
private String enable(String key) { return key.substring(0, key.lastIndexOf(JOB)) + "enable";}private String cronKey(String key) { return key.substring(0, key.lastIndexOf(JOB)) + "cron";}
所以我觉得配置文件应该是
#JobAa.job=test.com.jfinal.plugin.quzrtz.JobAa.job.cron=*/5 * * * * ?a.job.enable=true
或者是获得key的截取改一下
再次感谢jfinal 和jfinal-ext。