zoukankan      html  css  js  c++  java
  • 使用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系统地学一下

    保持着对万物的好奇心。即使是玩游戏,也要停下来想想这是怎么实现的。
  • 相关阅读:
    HttpWebRequest中的ContentType详解
    c# 创建Windows服务
    转载 Url编码
    在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的。
    IE兼容模式下 SCRIPT1028: 缺少标识符、字符串或数字
    Response.ContentLength获取文件大小
    unable to instantiate activity...
    查看android-support-v4.jar引出的问题
    导入项目 R.java没有
    初识python: 局部变量、全局变量
  • 原文地址:https://www.cnblogs.com/newflydd/p/4915740.html
Copyright © 2011-2022 走看看