使用Quartz创建定时任务

项目开发中经常需要定时循环执行某些任务

比如定时发送报表,定时发送邮件,亦或者定时清理缓存,定时更新数据等等

有些时候可以简单地利用Windows Server的计划任务执行程序

Linux也有相应的计划任务配置

但如果碰到比较复杂的循环定时

比如周一到周五的8点到18点,每隔1小时发送报表邮件

或者每个月的最后一个周六的晚上24:00对数据库进行备份等等

这时候我们需要一个稳定、灵活、轻量级的JAVA作业调度框架

Quartz呼之欲出

官网地址:http://www.quartz-scheduler.org/downloads

这个地址可能被墙,最新版本是2.2版

使用Quartz框架可以很方便实现复杂时间节点的作业调度

它的cron表达式相当好用,简单几个字符就可以制定您能想象出的任何时间规则

下面是博主使用简单代码,实现使用Quartz框架的作业调度

package com.newflypig.quartz;

import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;


/**
 *     使用Quartz创建定时任务,while循环一直执行下去
 *    @author newflypig
 *    time:2015年10月27日
 *    TODO 
 *
 */

public class QuartzDemo {

    public static void main(String[] args) throws Exception{
        //读取properties配置文件
        Properties prop=new Properties();
        prop.load(QuartzDemo.class.getResourceAsStream("/set.properties"));
        String toAccountId=prop.getProperty("toAccountId","fd60e46db0dc119cfea740c3375fd7c4");
        String cron=prop.getProperty("cron","0/10 * 8-18 * * ?");
        //创建Quartz的计划任务
        Scheduler sched = new StdSchedulerFactory().getScheduler();
        
     //配置计划任务的工作类名,这个类需要实现Job接口,在execute方法中实现所需要做的工作 JobDetail job
= newJob(ExportExcelAndPostInYixin.class).build();
//向工作类传递参数 job.getJobDataMap().put(
"toAccountId",toAccountId);
//配置计划任务的定时器 Trigger trigger
= newTrigger().withSchedule(cronSchedule(cron)).build(); Date date=sched.scheduleJob(job, trigger);//获得首次将要执行计划任务的时间,待会儿println出来 sched.start();//开始执行 System.out.println("first time run at:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
//无限循环下去
boolean flag=true; while(flag){ Thread.sleep(24*3600*1000); } sched.shutdown(); } }

下面给一个博主自己定时发送Excel报表到易信客户单的Job示例

package com.newflypig.quartz;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.newflypig.excel.OpenExcelDemo;
import com.newflypig.jpg.DrawFromExcel;
import com.newflypig.post.SendPostToYixin;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 *  导出Excel到PNG,并调用易信接口发送POST请求,推送PNG图片到指定好友
 *    @author newflypig
 *    time:2015年10月27日
 *    TODO 
 *
 */
public class ExportExcelAndPostInYixin implements Job {

    @Override
    public void execute(JobExecutionContext arg) throws JobExecutionException {
        String[] time=getTimeStr();
        String toAccountId=arg.getJobDetail().getJobDataMap().getString("toAccountId");    
        String access_token=arg.getJobDetail().getJobDataMap().getString("access_token");//修改Excel模板
        try {
            new OpenExcelDemo().doOpenExcel(...);            
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        
        //将Excel绘制成PNG
        String exportPNGPath=dirPath + time[1] + ".png";
        DrawFromExcel dfe=new DrawFromExcel();
        dfe.setExportPNGPath(exportPNGPath);
        dfe.setFileName(fileName);
        dfe.setSheetName(sheetName);
        dfe.setFromIndex(fromIndex);
        dfe.setToIndex(toIndex);
        try {
            dfe.draw();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        
        String pngFileName=time[1];
        try {
            SendPostToYixin.doPost(toAccountId,access_token,pngFileName,urlPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public String[] getTimeStr() {
        String[] time = new String[2];
        Date date=new Date();
        time[0]=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        time[1]=new SimpleDateFormat("yyyyMMddHHmmss").format(date);
        return time;
    }
}

至此就完成整个作业调度的结构

首先主程序中创建Scheduler计划任务,配置Job工作类,配置Trigger定时器,然后执行Scheduler

然后编写Job工作类,实现Job接口,也就是定义具体的execute函数

在讲一讲cron表达式,在上面的代码中,cron表达式是“0/10 * 8-18 * * ?”这样一组字符串

我们可以这样看

0/10 * 8-18 * * ?

秒    分  时 日 周 月(年,最后一个年份可以隐藏不写)

从左到右依次是上面的时间维度,这组字符串的含义是:

每10秒执行一次,分钟不限制,时间控制在8点-18点,日期,周数,月份,年度都不限制

其中用*表示在此维度上任意一个值都需要执行,用?表示在此维度上不限制,?只能用在日、周、月维度

第一个维度使用0/10表示每隔10秒执行一次,并且初试时间是0秒,依次执行时间将是0、10、20、30、40、50秒

如果我们改成3/10,表示初始时间是3秒,依次执行时间将是3、13、23、33、43、53秒

更详细的cron表达式大家可以到http://www.cnblogs.com/sunjie9606/archive/2012/03/15/2397626.html系统地学一下

保持着对万物的好奇心。即使是玩游戏,也要停下来想想这是怎么实现的。
原文地址:https://www.cnblogs.com/newflydd/p/4915740.html