使用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系統地學一下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章