JFinal Quartz 支持配置文件和持久化

原创
2015/05/27 21:07
阅读数 1.3K

    随着需求的增加,现在要定时启动一个调度和计划任务,原先写的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 Map<Job, String> jobs = new LinkedHashMap<>();
    private Map<String, String> 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<Map.Entry<Job, String>> set = jobs.entrySet();
                for (Map.Entry<Job, String> 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<Map.Entry<Job, String>> set = jobs.entrySet();
                for (Map.Entry<Job, String> 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<Map.Entry<String, String>> entries = jobProp.entrySet();
        for (Map.Entry<String, String> 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的配置文件是

#JobA
a.job=test.com.jfinal.plugin.quzrtz.JobA
a.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";
}

      所以我觉得配置文件应该是

#JobA
a.job=test.com.jfinal.plugin.quzrtz.JobA
a.job.cron=*/5 * * * * ?
a.job.enable=true

或者是获得key的截取改一下

再次感谢jfinal 和jfinal-ext。


展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
4 收藏
1
分享
返回顶部
顶部