Quartz任务调度——快速入门

目录

一、Quartz概念

二、Quartz运行环境

三、Quartz设计模式

四、Quartz学习的核心概念

五、Qutarz的体系结构

六、Quartz的几个常用API

七、Quartz的使用

八、Quartz监听器


一、Quartz概念

Quartz 是 OpenSymphony 开源组织在 Job scheduling 领域又一个开源项目,它可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。Quartz 可以用来创建简单调度,以执行十个,百个,甚至是好几万个 Jobs 这样复杂的程序。

简单来说,quartz就是基于java实现的任务调度框架,用于执行你想要的任何任务。

二、Quartz运行环境

Quartz可以运行嵌入在另一个独立式应用程序
Quartz可以在应用程序服务器(或servlet容器)内被实例化,并且参与事务
Quartz可以作为一个独立的程序运行(其自己的Java虚拟机内),可以通过RMl使用
Quartz可以被实例化,作为独立的项目集群(负载平衡和故障转移功能),用于作业的执行

三、Quartz设计模式

Builder模式

Factory模式

组件模式

链式编程

四、Quartz学习的核心概念

①任务job

job就是想要实现的任务类,每个job必须实现org,quartz.job接口,且只需实现接口的excute()方法

②触发器Trigger

Trigger为你执行任务的触发器,比如你想每天三点定时发送一份邮件,Trigger会设置3点执行该任务

③调度器Scheduler

Scheduler为任务的调度器,它会将任务job及触发器Trigger整合起来,负责基于Trigger设定的时间来执行job。

五、Qutarz的体系结构

六、Quartz的几个常用API

以下是Quartz编程API几个重要接口,也是Quartz的重要组件.

Scheduler 用于与调度程序交互的主程序接口。
Scheduler调度程序-任务执行计划表,只有安排进执行计划的任务Job(通过scheduler.scheduleJob方法安排进执行计划),当它预先定义的执行时间到了的时候(任务触发trigger ),该任务才会执行。
Job我们预先定义的希望在未来时间能被调度程序执行的任务类,我们可以自定义。
JobDetail使用jobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建的。JobDataMap可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法。
Trigger触发器,Trigger对象是用来触发执行ob的。当调度一个job时,我们实例一个触发器然后调整它的属性来满足job执行的条件。表明任务在什么时候会执行。定义了一个已经被安排的任务将会在什么时候执行的时间条件,比如每2秒就执行一次。
JobBuilder -用于声明一个任务实例,也可以定义关于该任务的详情比如任务名、组名等,这个声明的实例将会作为一个实际执行的任务。
TriggerBuilder触发器创建器,用于创建触发器trigger实例。
JobListener、TriggerListener、SchedulerListener监听器,用于对组件的监听。

七、Quartz的使用

入门案例

public class HelloJob implements Job {
    @Override
    public void excute(JobExecutionContext context)throws JobExecutionException{
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //工作内容
        System.out.println("正在执行数据库的备份工作,备份数据库的时间:"+dateString);
    }
}
public class HelloSchedulerDemo {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloJob.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                . build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startNow()//马上启动触发器
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5) ) //每5秒重复执行一次
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

Job和JobDetail介绍

job:工作任务调度的接口,任务类需要实现该接口,该接口中定义excute方法,类似JDK提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑
Job实例在Quartz中的生命周期:每次调度器执行Job时,它在调用execute方法前会创建一个新的job实例 ,当调用完成后,关联的Job对象实例会被释放,释放的实例会被垃圾回收机利回收。
jobDetail:jobDetail为job实例提供了许多设置属性,以及jobDetaMap成员变量属性,它用来存储特定job实例的状态信息,调度器需要借助jobDetail对象来添加job实例
jobDetail重要属性:name、group、jobClass、jobDataMap

        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloJob.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                . build();
        System.out.println("name: "+jobDetail.getKey().getName());
        System.out.println("组的名称:"+jobDetail.getKey().getGroup());//如果没有组名:Default
        System.out.println("任务类:"+jobDetail.getJobClass().getName());

实现效果:

 JobExecutionContext介绍

①当Scheduler调用一个job ,就会将]obExecutionContext传递给Job的execute()方法;
②Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。

    //获取JobDetail的内容
        JobKey jobKey= jobExecutionContext.getJobDetail().getKey();
        System.out.println("工作任务名称:"+jobKey.getName()+"  ;工作任务的组:"+jobKey.getGroup());
        System.out.println("任务类的名称(带路径):"+jobExecutionContext.getJobDetail().getJobClass().getName());
        System.out.println("任务类的名称:"+jobExecutionContext.getJobDetail().getJobClass().getSimpleName());

 JobDataMap介绍

(1)使用Map获取

●在进行任务调度时, JobDataMap存储在JobExecutionContext中,非常方便获取。
●JobDataMap可以用来装载任何可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它。
●JobDataMap实现了JDK的Map接口,并且添加了非常方便的方法用来存取基本数据类型。
HelloSchedulerDemo.java

public class HelloSchedulerDemo {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloJob.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .usingJobData("message","打印日志") //传递参数,名称message
                . build();
        System.out.println("name: "+jobDetail.getKey().getName());
        System.out.println("组的名称:"+jobDetail.getKey().getGroup());//如果没有组名:Default
        System.out.println("任务类:"+jobDetail.getJobClass().getName());

        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startNow()//马上启动触发器
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5) ) //每5秒重复执行一次
                .usingJobData("message","simple触发器") //传递参数,名称message
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

HelloJob.java

public class HelloJob implements Job {

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //获取JobDetail的内容
        JobKey jobKey= jobExecutionContext.getJobDetail().getKey();
        System.out.println("工作任务名称:"+jobKey.getName()+"  ;工作任务的组:"+jobKey.getGroup());
        System.out.println("任务类的名称(带路径):"+jobExecutionContext.getJobDetail().getJobClass().getName());
        System.out.println("任务类的名称:"+jobExecutionContext.getJobDetail().getJobClass().getSimpleName());

        //从JobDetail对象中获取jobDataMap的数据
        JobDataMap jobDataMap=jobExecutionContext.getJobDetail().getJobDataMap();
        String jobDataMessage = jobDataMap.getString("message");
        System.out.println("任务数据的参数值:"+jobDataMessage);
        //获取Trigger对象中获取jobDataMap的数据
        JobDataMap triggerDataMap = jobExecutionContext.getTrigger().getJobDataMap();
        String triggerDataMessage=triggerDataMap.getString("message");
        System.out.println("触发器的参数值:"+triggerDataMessage);
        //获取Trigger的内容
        TriggerKey key=jobExecutionContext.getTrigger().getKey();
        System.out.println("触发器名称:"+key.getName()+" ;触发器的组:"+key.getGroup());
        //获取其他内容
        System.out.println("当前任务的执行时间:"+dateFormat.format(jobExecutionContext.getFireTime()));
        System.out.println("下一次任务的执行时间:"+dateFormat.format(jobExecutionContext.getNextFireTime()));

        //工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:"+dateString);
    }
}

(2 ) Job实现类中添加setter方法对应JobDataMap的键值, Quartz框架默认的jobFactory实现类在初始化job实例对象时会自动地调用这些setter方法。

    private String message;

    public void setMessage(String message) {
        this.message = message;
    }

注意:如果遇到同名的key,Trigger中的.usingJobData("message","simple触发器")会覆盖JobDetail中的.usingJobData("message","打印日志")

有状态的job和无状态的job

@PersistJobDataAfterExecution注解的使用//多次调用job的时候,会对job进行持久化,即保存一个数据信息
有状态的job可以理解为多次Job调用期间可以持有一些状态信息。这些状态信息存储JobDataMap中,而默认的无状态job每次调用时都会创建一个新的JobDataMap。

HelloJob类没有添加@PersistjobDataAfterExecution注解,每次调用时都会创建一个新的JobDataMap。不会累加;
HelloJob类添加@PersistJobDataAfterExecution注解,多次Job调用期间可以持有一些状态信息,即可以实现count的累加。

Trigger的介绍

 Quartz有一些不同的触发最类型,不过,用得最多的是SimpleTrgger和CronTrigger,
(1 ) jobKey
表示job实例的标识,触发器被触发时,该指定的job实例会被执行。
( 2 ) startTime
表示触发器的时间表,第一次开始被触发的时间 ,它的教据类型是java.util.Date.
( 3 ) endTime
指定触发器终止被触发的时间,它的数据类型是java.util.Date.

HelloTrigger.java 
@PersistJobDataAfterExecution //多次调用job的时候,会对job进行持久化,即保存一个数据信息
public class HelloTrigger implements Job {


    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //获取JobDetail的内容
        JobKey jobKey= jobExecutionContext.getJobDetail().getKey();
        System.out.println("工作任务名称:"+jobKey.getName()+"  ;工作任务的组:"+jobKey.getGroup());
        System.out.println("任务类的名称(带路径):"+jobExecutionContext.getJobDetail().getJobClass().getName());
        System.out.println("任务类的名称:"+jobExecutionContext.getJobDetail().getJobClass().getSimpleName());

        //从JobDetail对象中获取jobDataMap的数据
        JobDataMap jobDataMap=jobExecutionContext.getJobDetail().getJobDataMap();
        String jobDataMessage = jobDataMap.getString("message");
        System.out.println("任务数据的参数值:"+jobDataMessage);
        //获取Trigger对象中获取jobDataMap的数据
        JobDataMap triggerDataMap = jobExecutionContext.getTrigger().getJobDataMap();
        String triggerDataMessage=triggerDataMap.getString("message");
        System.out.println("触发器的参数值:"+triggerDataMessage);
        //获取Trigger的内容
        TriggerKey key=jobExecutionContext.getTrigger().getKey();
        System.out.println("触发器名称:"+key.getName()+" ;触发器的组:"+key.getGroup());
        //获取其他内容
        System.out.println("当前任务的执行时间:"+dateFormat.format(jobExecutionContext.getFireTime()));
        System.out.println("下一次任务的执行时间:"+dateFormat.format(jobExecutionContext.getNextFireTime()));

        //工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:"+dateString);

        //获取jobKey、startTime、endTime
        Trigger trigger=jobExecutionContext.getTrigger();
        System.out.println("jobKey的名称:"+trigger.getJobKey().getName()+"jobKey的组名称:"+trigger.getJobKey().getGroup());
        System.out.println("任务的开始时间:"+dateFormat.format(trigger.getStartTime())+"任务的结束时间:"+dateFormat.format(trigger.getEndTime()));
    }
}
HelloSchedulerDemoTrigger.java
public class HelloSchedulerDemoTrigger {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //设置任务的开始时间
        Date startDate=new Date();
        //任务的开始时间推迟三秒
        startDate.setTime(startDate.getTime()+3000);
        //设置任务的结束时间
        Date endDate=new Date();
        //任务的结束时间推迟10秒(10秒后停止)
        endDate.setTime(endDate.getTime()+10000);
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloTrigger.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .usingJobData("message","打印日志") //传递参数,名称message
                .build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
//                .startNow()//马上启动触发器
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5))
                .startAt(startDate) //设置任务的开始时间
                .endAt(endDate)//设置任务的结束时间
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

SimpleTrigger触发器

SimpleTrigger对于设置和使用是最为简单的一种QuartzTrigger.
它是为那种需要在特定的日期/时间启动,且以一个可能的间隔时间重复执行n次的Job所设计的。

案例一:表示在一个指定的时间段内,执行一次作业任务

@PersistJobDataAfterExecution //多次调用job的时候,会对job进行持久化,即保存一个数据信息
public class HelloSimpleTrigger implements Job {
    
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:"+dateString);

    }
}

public class HelloSchedulerDemoSimpleTrigger {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //设置任务的开始时间
        Date startDate=new Date();
        //任务的开始时间推迟三秒
        startDate.setTime(startDate.getTime()+3000);
        //设置任务的结束时间
        Date endDate=new Date();
        //任务的结束时间推迟10秒(10秒后停止)
        endDate.setTime(endDate.getTime()+10000);
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloSimpleTrigger.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .usingJobData("message","打印日志") //传递参数,名称message
                .build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startAt(startDate) //设置任务的开始时间
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

案例二:或在指定的时间间隔内多次执行作业任务

        // 3:触发器(Trigger),马上执行,然后每5秒重复执行一次
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startAt(startDate) //设置任务的开始时间
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5).withRepeatCount(3))//5秒后重复执行,只重复执行4次(默认值是0)
                .build();

案例三:指定任务的结束时间

        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //设置任务的开始时间
        Date startDate=new Date();
        //任务的开始时间推迟三秒
        startDate.setTime(startDate.getTime()+3000);
        //设置任务的结束时间
        Date endDate=new Date();
        //任务的结束时间推迟10秒(10秒后停止)
        endDate.setTime(endDate.getTime()+10000);
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloSimpleTrigger.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .usingJobData("message","打印日志") //传递参数,名称message
                .build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startAt(startDate) //设置任务的开始时间
                .endAt(endDate)
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5).withRepeatCount(3))//5秒后重复执行,只重复执行4次(默认值是0)
                .build();

需要注意的点
●SimpleTrigger的属性有 :开始时间、结束时间、重复次数和重复的时间间隔。
●重复次数属性的值可以为0、正整数、或常量SimpleTrigger.REPEAT_ INDEFINITELY。
●重复的时间间隔属性值必须为大于0或长整型的正整数,以毫秒作为时间单位,当重复的时间间隔为0时,意味着与Trigger同时触发执行。
●如果有指定结束时间属性值,则结束时间属性优先于重复次数属性,这样的好处在于:当我们需要创建一个每间隔10秒钟触发一次直到指定的结束时间的 Trigger ,而无需去计算从开始到结束的所重复的次数,我们只需简单的指定结束时间和使用REPEAT_ INDEFINITELY作为重复次数的属性值即可。

CronTrigger触发器
如果你需要像日历那样按日程来触发任务,而不是像SimpleTrigger那样每隔特定的间隔时间触发, CronTriggers通常比SimpleTrigger更有用,因为它是基于日历的作业调度器。
使用CronTrigger ,你可以指定诸如“每个周五中午”,或者"每个工作日的9:30"”或者“从每个周一-、周三、周五的上午9 : 00到上午10 : 00之间每隔五分钟”这样日程安排来触发。甚至,像SimpleTrigger一样,CronTrigger也有一个startTIme以指定日程从什么时候开始,也有一一个 (可选的) endTIme以指定何时日程不再继续。
Cron表达式被用来配置CronTrigger实例。Cron表达式是一个由7个子表达式组成的字符串。每个子表达式都描述了一个单独的日程细节。这些子表达式用空格分隔,分别表示:
1. Seconds秒
2. Minutes分钟
3. Hours小时
4. Day-oF-Month月中的天
5. Month月
6. Day-of-Week周中的天
7. Year (optional field)年(可选的城)

取值:

 单个子表达式可以包含范围或者列表。例如∶前面例子中的周中的天这个域(这里是"WED")可以被替换为"MON-FRI","MON, WED,FRI"或者甚至"MON-WED,SAT""。
所有的域中的值都有特定的合法范围,这些值的合法范围相当明显,例如∶秒和分域的合法值为0到59,小时的合法范围是0到23,Day-of-Month中值得合法凡范围是1到31,但是需要注意不同的月份中的天数不同。月份的合法值是1到12。或者用字符串JAN.FEB MAR,APR, MAY,JUN,JUL,AUG, SEP, OCT,NOV及DEC来表示。Days-of-Week可以用1到7来表示(1=星期日)或者用字符串SUN,MON,TUE, WED,THU, FRI和SAT来表示.

@PersistJobDataAfterExecution //多次调用job的时候,会对job进行持久化,即保存一个数据信息
public class HelloCronTrigger implements Job {

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间是:"+dateString);

    }
}
public class HelloSchedulerDemoCronTrigger {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //设置任务的开始时间
        Date startDate=new Date();
        //任务的开始时间推迟三秒
        startDate.setTime(startDate.getTime()+3000);
        //设置任务的结束时间
        Date endDate=new Date();
        //任务的结束时间推迟10秒(10秒后停止)
        endDate.setTime(endDate.getTime()+10000);
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloCronTrigger.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .usingJobData("message","打印日志") //传递参数,名称message
                .build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
//                .startAt(startDate) //设置任务的开始时间
//                .endAt(endDate)//设置任务的结束时间
                  .startNow() //马上开始
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * 9 4 ?"))//日历 每5秒执行一次
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

小提示:
L和W可以一起使用J(企业可用在工资计算)
'#'可表示月中第几个周几。(企业可用在计算母亲节和父亲节)
周字段英文字母不区分大小写,例如MON==mon。
利用工具,在线生成。

大家都知道,一个作业,比较重要的三个要素就是Schduler , jobDetail , Trigger ;而Trigger对于job而言就好比一个驱动器;没有触发器来定时驱动作业,作业就无法运行;对于Job而言,一个job可以对应多个Trigger,但对于Trigger而言,一个Trigger只能对应一个job;所以一
个Trigger只能被指派给一个Job;如果你需要一个更复杂的触发计划,你可以创建多个Trigger并指派它们给同一个Job。

scheduler的创建方式:

stdSchedulerFactory:
Quartz默认的SchedulerFactory
使用一组参数( java.util.Properties)来创建和初始化Quartz调度器
配置参数一般存储在quartz.properties文件中
调用getScheduler方法就能创建和初始化调度器对象

SchedulerFactory schedulerFactory = new stdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getscheduler();



我们也可以在项目的资源下添加quartz.properties文件,去覆盖底层的配置文件。

组成部分
调度器属性
org.quartz.scheduler.instanceName属性用来区分特定的调度器实例,可以按照功能用途来给调度器起名。org.quartz.scheduler.nstanceld属性和前者一样,也允许任何字符串,但这个值必须在所有调度器实例中是唯一的,尤其是在一个集群环境中,作为集群的唯一key。假如你想Quartz帮你生成这个值的话,可以设置为AUTO。

线程池属性
threadCount
处理]ob的线程个数,至少为1,但最多的话最好不要超过100,在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的Job执行时间较长的情况下
threadPriority
线程的优先级,优先级别高的线程比级别低的线程优先得到执行。最小为1,最大为10,默认为5

org.quartz.threadPool.class
一个实现了org.quartz.spi.ThreadPool接口的类,Quartz自带的线程池实现类是org.quartz.smpl.SimpleThreadPool
·作业存储设置
描述了再调度器实例的生命周期+,Job和Trigger信息是如何被存储的。·插件配置
满足特定需求用到的Quartz插件的配置。
·插件配置
满足特定需求用到的Quartz插件的配置。


八、Quartz监听器

 概念

Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。 类似于任务执行过程中的邮件、短信类的提醒。Quartz监听器主要有JobListener、TriggerListener、 SchedulerListener三种 ,顾名思义,分别表示任务、触发器、调度器对应的监听器。三者的使用方法类似,在开始介绍三种监听器之前,需要明确两个概念:全局监听器与非全局监听器,二者的区别在于:
全局监听器能够接收到所有的Job/Trigger的事件通知,
而非全局监听器只能接收到在其上注册的Job或Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。

JobListener

任务调度过程中,与任务]ob相关的事件包括i job开始要执行的提示job执行完成的提示灯
1) getName方法︰用于获取该JobListener的名称。
2) jobToBeExecuted方法:Scheduler在JobDetail将要被执行时调用这个方法。
3) jobExecutionVetoed方法 :Scheduler在obDetail即将被执行,但又被TriggerListerner否决时会调用该方法
4) jobWasExecuted方法: Scheduler在JobDetail被执行之后调用这个方法

@PersistJobDataAfterExecution //多次调用job的时候,会对job进行持久化,即保存一个数据信息
public class HelloJobListener implements Job {

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //工作内容
        System.out.println("正在进行数据库的备份工作,备份数据库的时间:"+dateString);
    }
}

TiggerListener

任务调度过程中,与触发器Trigger相关的事件包括︰触发器触发、触发器未正常触发、触发器完成等。

public interface TriggerListener {

    String getName();

    
    void triggerFired(Trigger trigger, JobExecutionContext context);

    boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);

    
    void triggerMisfired(Trigger trigger);


    void triggerComplete(Trigger trigger, JobExecutionContext context,
            CompletedExecutionInstruction triggerInstructionCode);

}
public class HelloSchedulerDemoTriggerListener {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloJobListener.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startNow()//马上启动触发器
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5).withRepeatCount(3))
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //创建并注册一个全局的Trigger Listener
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("simplename"), EverythingMatcher.allTriggers());
        //创建并注册一个局部的Trigger Listener
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("simplename"), KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger1","group1")));
        //启动
        scheduler.start();
    }
}
public class MyTriggerListener implements TriggerListener {

    private String name;
    //构造方法,自定义传递的名称,默认是MyTriggerListener
    public MyTriggerListener(String name){
        this.name=name;
    }

    @Override
    public String getName() {
        String name = this.getClass().getSimpleName();
        System.out.println("触发器的名称:"+name);
        return name;
    }

    @Override
    public void triggerFired(Trigger trigger, JobExecutionContext context) {
        String name = trigger.getKey().getName();
        System.out.println(name+"被触发");
    }

    @Override
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
        String name=trigger.getKey().getName();
        System.out.println(name+"没有被触发");
        return true; //true:表示不会执行job的方法
    }

    @Override
    public void triggerMisfired(Trigger trigger) {
        String name = trigger.getKey().getName();
        //Scheduler调用这个方法是在Trigger错过触发时
        System.out.println(name+"错过触发");
    }

    @Override
    public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
        String name = trigger.getKey().getName();
        //Trigger被触发并且完成了Job的执行,Scheduler调用这个方法
        System.out.println(name+" 完成之后触发");

    }
}

其中:
1) getName方法︰用于获取触发器的名称
2)triggerFired方法:当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,Scheduler就调用该方法。
3) vetoJobExecution方法:在Trigger触发后,Job将要被执行时由Scheduler调用这个方法。TriggerListener给了一个选择去否决Job的执行。假如这个方法返回true,这个Job将不会为此次Trigger触发而得到执行。
4)triggerMisfired方法 :Scheduler调用这个方法是在Trigger错过触发时。你应该关注此方法中持续时间长的逻辑∶在出现许多错过触发的Trigger时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小。
5) triggerComplete方法:Trigger被触发并且完成了Job的执行时,Scheduler调用这个方法。
 

SchedulerListener

SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括∶增加一个job/trigger,删除一个job/trigger , scheduler发生严重错误,关闭scheduler等。
 

public interface SchedulerListener {

    void jobScheduled(Trigger trigger);

    void jobUnscheduled(TriggerKey triggerKey);

    void triggerFinalized(Trigger trigger);

    void triggerPaused(TriggerKey triggerKey);

    void triggersPaused(String triggerGroup);

    void triggerResumed(TriggerKey triggerKey);

    void triggersResumed(String triggerGroup);

    void jobAdded(JobDetail jobDetail);

    void jobDeleted(JobKey jobKey);

    void jobPaused(JobKey jobKey);

    void jobsPaused(String jobGroup);
    

    void jobResumed(JobKey jobKey);

    void jobsResumed(String jobGroup);

    void schedulerError(String msg, SchedulerException cause);

    void schedulerInStandbyMode();

    void schedulerStarted();

    void schedulerStarting();

    void schedulerShutdown();

    void schedulerShuttingdown();

    void schedulingDataCleared();
}

其中:
1) jobScheduled方法∶用于部署JobDetail时调用2) jobUnscheduled方法∶用于卸载JobDetail时调用Ⅰ
3)triggerFinalized方法:当一个Trigger来到了再也不会触发的状态时调用这个方法。除非这个Job已设置成了持久性,否则它就会从Scheduler中移除。
4)triggersPaused方法 :Scheduler调用这个方法是发生在一个Trigger或Trigger组被暂停时。假如是Trigger组的话,triggerName参数将为null。
5) triggersResumed方法 :Scheduler调用这个方法是发生成一个Trigger或 Trigger组从暂停中恢复时,假如是Trigger组的话,假如是Trigger组的话,triggerName参数将为null。参数将为null。
6) jobsPaused方法:当一个或一组JobDetail暂停时调用这个方法。
7)jobsResumed方法:当一个或一组Job从暂停上恢复时调用这个方法。假如是一个Job组,jobName参数将为null。

8) schedulerError方法∶在Scheduler的正常运行期间产生一个严重错误时调用这个方法
9) schedulerStarted方法:当Scheduler开启时,调用该方法
10) schedulerlnStandbyMode方法:当Scheduler处于StandBy模式时,调用该方法
11) schedulerShutdown方法:当Scheduler停止时,调用该方法
12) schedulingDataCleared方法:当Scheduler中的数据被清除时,调用该方法。


 

public class HelloSchedulerDemoSchedulerListener {
    public static void main(String[] args) throws Exception {
        // 1:调度器(Scheduler) ,从工厂中获取调度的实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        // 2:任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloJobListener.class)//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1", "group1")// 参数1:任务的名称(唯- 实例) ;参数2:任务组的名称
                .build();
        // 3:触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")// 参数1:触发器的名称(唯一实例) ;参数2:触发器组的名称
                .startNow()//马上启动触发器
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5).withRepeatCount(3))
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //串讲调度器的监听
        scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());
        //移除对应的调度器的监听
        scheduler.getListenerManager().removeSchedulerListener(new MySchedulerListener());
        //启动
        scheduler.start();
        //线程延迟7秒后关闭
        Thread.sleep(7000L);
        //关闭调度器
        scheduler.shutdown();
    }
}
public class MySchedulerListener implements SchedulerListener {
    @Override
    public void jobScheduled(Trigger trigger) {
        String name=trigger.getKey().getName();
        //用于部署JobDetail时调用
        System.out.println(name+"完成部署");
    }

    @Override
    public void jobUnscheduled(TriggerKey triggerKey) {
        //用于卸载JobDetail时调用
        String name = triggerKey.getName();
        System.out.println(name+"完成卸载");
    }

    @Override
    public void triggerFinalized(Trigger trigger) {
        String name = trigger.getKey().getName();
        //当一个Trigger来到了再也不会触发的状态时调用这个方法。除非这个Job已设置成了持久性,否则它就会从Scheduler中移除。
        System.out.println("触发器被移除");
    }

    @Override
    public void triggerPaused(TriggerKey triggerKey) {
        String name = triggerKey.getName();
        //Scheduler调用这个方法是发生在一个Trigger或Trigger组被暂停时。假如是Trigger组的话,triggerName参数将为null。
        System.out.println(name+"正在被暂停");
    }

    @Override
    public void triggersPaused(String triggerGroup) {
        //
        System.out.println("触发器组"+triggerGroup+" 正在被暂停");
    }

    @Override
    public void triggerResumed(TriggerKey triggerKey) {
        //triggersResumed方法 :Scheduler调用这个方法是发生成一个Trigger或 Trigger组从暂停中恢复时,假如是Trigger组的话,假如是Trigger组的话,triggerName参数将为null。参数将为null。
        String name=triggerKey.getName();
        System.out.println(name+"正在从暂停中");
    }

    @Override
    public void triggersResumed(String triggerGroup) {
      //
        System.out.println("触发器组"+triggerGroup+"正在从暂停中恢复");
    }

    @Override
    public void jobAdded(JobDetail jobDetail) {
        System.out.println(jobDetail.getKey()+"添加工作任务");
    }

    @Override
    public void jobDeleted(JobKey jobKey) {
        System.out.println(jobKey+"删除工作任务");
    }

    @Override
    public void jobPaused(JobKey jobKey) {
        System.out.println(jobKey+"工作任务正在被暂停");
    }

    @Override
    public void jobsPaused(String jobGroup) {
        System.out.println("工作组"+jobGroup+"正在被暂停");
    }

    @Override
    public void jobResumed(JobKey jobKey) {
        System.out.println(jobKey+"正在从暂停中恢复");
    }

    @Override
    public void jobsResumed(String jobGroup) {
        System.out.println("工作组"+jobGroup+"正在从暂停中恢复");
    }

    @Override
    public void schedulerError(String msg, SchedulerException cause) {
        //在Scheduler的正常运行期间产生一个严重错误时调用这个方法
        System.out.println("产生严重错误的时候调用"+msg+" "+cause.getUnderlyingException());
    }

    @Override
    public void schedulerInStandbyMode() {
        //当Scheduler处于StandBy模式时,调用该方法
        System.out.println("调度器被挂起模式的时候调用");
    }

    @Override
    public void schedulerStarted() {
    //当Scheduler开启时,调用该方法
        System.out.println("调度器开启的时候调用");
    }

    @Override
    public void schedulerStarting() {
        System.out.println("调度器正在开启的时候调用");
    }

    @Override
    public void schedulerShutdown() {
        System.out.println("调度器关闭的时候调用");
    }

    @Override
    public void schedulerShuttingdown() {
        System.out.println("调度器正在关闭的时候调用");
    }

    @Override
    public void schedulingDataCleared() {
        //当Scheduler中的数据被清除时,调用该方法。
        System.out.println("调度器的数据被清除的时候");
    }
}

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龍弟-idea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值