Quartz

Quartz

核心概念

  • 任务job

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

  • 触发器Trigger

Trigger为你执行任务的触发器,比如你每天定时3点发送一份统计邮件,Trigger将会设置3点执行该任务。Trigger主要包括Simple Trigger和CronTrigger两种。

  • 调度器Scheduler

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

Quartz的常用的几个API

  • Scheduler用于与调度程序交互的主程序接口。

    Scheduler调度程序-任务执行计划表,只有安排进执行计划的任务job(通过scheduler.scheduleJob方法安排进执行计划),当它到了预先定义的执行时间

    该任务才会启动

  • Job我们预先定义的希望在未来定时任务的实例,我们可以自定义

  • JobDetail 使用JobDetail 来定义定时任务的实例,该实例是通过JobBuilder类创建的

  • JobDataMap:可以包含不限量的数据对象,在Job实例执行的时候,可以使用其中的数据,JobDataMap是Java Map接口的一个实现,额外增加了一些存储基本数据类型的数据方法

  • Trigger触发器:Trigger对象是用来出发执行Job的,当调度一个Job时,我们实例一个出发去然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行,定义了一个已经被安排的任务会在什么时候执行的时间条件:比两秒一次

  • JobBuilder:用于声明一个任务实例,也可以定义关于该任务的详情比如任务名,组名等,这个声明的实例将会作为一个实例执行的任务

  • TriggerBuilder:触发器的创建器,用于创建触发器trigger实例

  • JobListener、TriggerListener、SchedulerListener监听器,用于对组件的监听

入门案例

  • 首先有一个java类 也就是需要实现的任务
public class Hellojob implements Job {

    public void execute(JobExecutionContext context){
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = dateFormat.format(date);
        //工作内容
        System.out.println("时间是"+format);

    }
}
  • 创建任务调度类
public class HelloSchedulerDemo {

    public static void main(String[] args) throws SchedulerException {
        //调度器 Scheduler 获取实例调度
        Scheduler fact = StdSchedulerFactory.getDefaultScheduler();

        //任务实例JobBulider
        JobDetail jobDetail = JobBuilder.newJob(Hellojob.class)
                .withIdentity("job1", "group1")//参数一 任务名称 唯一实例 参数二 任务组名称
                .build();

        //触发器 Trigger
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")//参数一 任务名称 唯一实例 参数二 任务组名称
                .startNow()//马上启动
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5))//设置每5秒执行一次
                .build();

        //让调度器去关联触发器 保证触发器定义的条件执行任务
        fact.scheduleJob(jobDetail,trigger);
        fact.start();

    }
}

Job与JobDetail介绍

  • Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似JDK提供的TimeTask类的run方法,在里面编写业务逻辑

  • Job实例在Quartz中的生命周期,每次调度器执行Job时,它在调用execute方法前会创建一个新的Job实例,当调度完成后,关联的Job对象实例会完全释放,释放的实例会被垃圾回收机制回收

  • JobDetail:JobDetail为Job实录提供了许多属性,以及JobDateMap成员变量属性,它用来存储特定job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例

  • public static void main(String[] args) throws SchedulerException {
        //调度器 Scheduler 获取实例调度
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    
        //任务实例JobBulider
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                .withIdentity("job1","group1")
                .usingJobData("message","打印日志")
                .build();
        System.out.println(jobDetail.getKey().getGroup());
        System.out.println(jobDetail.getKey().getName());
        System.out.println(jobDetail.getKey().getClass());
    

JobExecutionContext介绍

  • 当Scheduler调用一个job,就会将JonExecutionContext传递给Job的execute()方法

  • Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及job本身的明细数据

JobDataMap介绍

  • 使用Map获取

  • 在进行任务调度时,jobDataMap存储在JobExecutionContext中,非常方便获取

    • public class HelloScheduleDemo {
      
          public static void main(String[] args) throws SchedulerException {
              //调度器 Scheduler 获取实例调度
              Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
      
              //任务实例JobBulider
              JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                      .withIdentity("job1","group1")
                      .usingJobData("message","打印日志")
                  	//添加信息
                      .build();
              System.out.println(jobDetail.getKey().getGroup());
              System.out.println(jobDetail.getKey().getName());
              System.out.println(jobDetail.getKey().getClass());
              //触发器Trigger
              Trigger trigger = TriggerBuilder.newTrigger()
                      .withIdentity("trigger1","group1")
                      .startNow()
                      .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
                      .usingJobData("message","simple触发器")
                  //添加信息
                  
                  
                      .build();
      
              //让调度器去关联触发器,保证触发器定义的条件执行任务
              scheduler.scheduleJob(jobDetail,trigger);
              scheduler.start();
          }
      
      }
      

可以在HelloJob中获取

 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
        String format = dateFormat.format(date);

        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        //从JobDetail中获取JobDataMap的数据
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        System.out.println(jobDataMap.getString("message"));

        //从Trigger中获取JobDataMap的数据
        JobDataMap jobDataMap1 = jobExecutionContext.getTrigger().getJobDataMap();
        System.out.println(jobDataMap1.getString("message"));

        System.out.println("时间是:"+format);
    }
}

也可以用setter方法来获取trigger或者JobBulider中的值

但是如果trigger与JobBulider都有一个相同的变量那只会输出trigger中的值

    private String message;

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

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
        String format = dateFormat.format(date);

        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        //从JobDetail中获取JobDataMap的数据
//        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
//        System.out.println(jobDataMap.getString("message"));

        //从Trigger中获取JobDataMap的数据
//        JobDataMap jobDataMap1 = jobExecutionContext.getTrigger().getJobDataMap();
//        System.out.println(jobDataMap1.getString("message"));

        //从set方法中读出
        System.out.println(message);//输出simple触发器
        System.out.println("时间是:"+format);
    }

有状态的Job和无状态的Job

  • 有状态的Job可以理解为多次Job调用期间可以持有一些状态信息,这些状态信息存储在JobDataMap中,而默认的无状态的Job每次调用是会创建一个新的JobDataMap

  • @PersistJobDataAfterExecution//多次调用Job的时候,会对Job进行持久化,即保存一个数据的信息
    
  • 在配置类中传入一个参数count,初始值为0

    JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
            .withIdentity("job1","group1")
            .usingJobData("message","打印日志")
            .usingJobData("count",0)
            .build();
    
  • 在Job类中加上注解@PersistJobDataAfterExecution,使用set方法得到count

private int count;

public void setCount(int count) {
    this.count = count;
}

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            ++count;
        System.out.println(count);
   jobExecutionContext.getJobDetail().getJobDataMap().put("count",count);//将数据放到JobDataMap里面、这样每次的count都会递增
    
}

Trigger介绍

  • Jobkey:表示Job实例的标识,触发器被触发时,该指定的job实例会被执行
  • startTime:设置触发器第一次被触发的时间
  • endTime:设置触发器被终止触发的时间

SimpleTrigger触发器

  • SimpleTrigger对于设置和使用手机一种最为简单的QuartzTrigger
  • 它是为那种需要在特定的日期/时间启动且以一个可能的间隙时间重复执行n次的Job所设计
//触发器Trigger
Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1","group1")
        .startAt(startDate)//设置任务的开始时间
		.endAt(endDate)        #设置任务结束时间        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)//每5秒执行一次,只执行4次 从0开始
                .withRepeatCount(3))
        .build();
  • 如果指定的结束时间与指定的次数相互冲突,则结束时间的属性优先级是优于重复属性

CronTrigger触发器

  • 如果你需要像日历那样的按日程来触发任务,而不是像SimpleTrigger那样每隔特定的时间间隔触发,CronTrigger比SimpleTrigger更有用

  • 使用CronTrigger,你可以指定诸如“每个周五中午”,或者“每个工作日的9:30”

    这样的日程安排来触发

  • 案例

//触发器Trigger
Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1","group1")
        .startNow()
        .withSchedule(CronScheduleBuilder.cronSchedule("0-30 * * * * ?"))//设置你想要触发的时间 如上表的案例
        .usingJobData("message","simple触发器")
        .build();

Scheduler

  • 创建

    Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    
  • scheduler.scheduleJob(jobDetail, trigger);//让调度器去关联触发器,保证触发器定义的条件执行任务
    
    scheduler.start();  //启动 
    scheduler.standby();//挂起
    scheduler.shutdown(true);//关闭,但是在所有的Job任务结束后才关闭
    scheduler.shutdown(false);//关闭,直接关闭,不会等待Job任务的结束
    

监听器

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

JobListener

  • 任务调度过程中:与任务Job相关的事件包括:Job开始要执行的提示、Job执行完成的提示

  • 创建一个MyListener配置类

    
    
    
    public class MyJobListener implements JobListener {
    
        public String getName() {
            //监听器的名称
            String simpleName = this.getClass().getSimpleName();
            System.out.println("监听器的名称+ "+simpleName);
            return simpleName;
        }
    
        public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
            String name = jobExecutionContext.getJobDetail().getKey().getName();
            System.out.println("Scheduler在JobDetial将要被执行时调用的方法   job名称"+name);
        }
    
        public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
            String name = jobExecutionContext.getJobDetail().getKey().getName();
            System.out.println("Scheduler在JobDetail即将被执行,但又被TriggerListener否决时会调用该方法   job,名称"+name);
        }
    
        public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
            String name = jobExecutionContext.getJobDetail().getKey().getName();
            System.out.println("Scheduler在JobDetail被执行之后调用这个方法   job名称 "+name);
        }
    }
    

在HelloListenerDemo中注册监听



public class HelloJobListenerDemo {

    public static void main(String[] args) throws SchedulerException {
        //调度器 Scheduler 获取实例调度
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        //任务实例JobBulider
        JobDetail jobDetail = JobBuilder.newJob(HelloListener.class)
                .withIdentity("job1","group1")
                .usingJobData("message","打印日志")
                .usingJobData("count",0)
                .build();
        System.out.println(jobDetail.getKey().getGroup());
        System.out.println(jobDetail.getKey().getName());
        System.out.println(jobDetail.getKey().getClass());
        //触发器Trigger
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1","group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
                .usingJobData("message","simple触发器")
                .build();

        //让调度器去关联触发器,保证触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);

        //创建并注册一个全局的Job Listener
       // scheduler.getListenerManager().addJobListener(new MyJobListener(), EverythingMatcher.allJobs());

        //创建一个局部的Job Listener
        scheduler.getListenerManager().addJobListener(new MyJobListener(), KeyMatcher.keyEquals(JobKey.jobKey("job1","group1")));//这两个参数就是上面jobBulider中设置的withIdentity("job1","group1")中的两个参数
        scheduler.start();
    }
}

TriggerListener

  • 任务调度中,与触发器Trigger相关的事件包括:触发器触发、触发器未正常触发、触发器完成

  • 创建一个MyTriggerListener


  
      public String getName() {
          String name = this.getClass().getName();
          System.out.println("触发器的名称:"+name);
          return name;
      }
  
      public void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContext) {
          //当与监听器相关联的Trigger被触发、job上的execute()方法被执行时,Scheduler就调用该方法
          String name = trigger.getKey().getName();
          System.out.println(name+" 这个触发器触发");
      }
  
      public boolean vetoJobExecution(Trigger trigger, JobExecutionContext jobExecutionContext) {
          //在Trigger触发后,Job将要执行时,由Scheduler调用这个方法,TriggerListener给了一个选择去否决Job的执行
          //假如这个方法返回True,这个Job就不会为此次Trigger触发而得到执行
          String name = trigger.getKey().getName();
          System.out.println(name+" 没有被触发器触发");
          return false;
      }
  
      public void triggerMisfired(Trigger trigger) {
          /*Scheduler调用这个方法是在错过触发时,你应该关注此方法中持续时间长的逻辑*/
          String name = trigger.getKey().getName();
          System.out.println(name+" 错过触发");
      }
  
      public void triggerComplete(Trigger trigger, JobExecutionContext jobExecutionContext, Trigger.CompletedExecutionInstruction completedExecutionInstruction) {
         /*Trigger被触发并且完成了Job的执行时,Scheduler调用这个方法*/
          String name = trigger.getKey().getName();
          System.out.println(name+" 完成触发");
      }
  }

在HelloTriggerListener注册监听



public class HelloTriggerListener {

    public static void main(String[] args) throws SchedulerException {
        //调度器 Scheduler 获取实例调度
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        //任务实例JobBulider
        JobDetail jobDetail = JobBuilder.newJob(HelloTrigger.class)
                .withIdentity("job1","group1")
                .usingJobData("message","打印日志")
                .usingJobData("count",0)
                .build();

        //触发器Trigger
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1","group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
                .usingJobData("message","simple触发器")
                .build();

        //让调度器去关联触发器,保证触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);

        //创建并注册一个全局的Trigger Listener
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener(), EverythingMatcher.allTriggers());
		
        
        //  //创建并注册一个局部的Trigger Listener
        //scheduler.getListenerManager().addTriggerListener(new MyTriggerListener(),KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger","group1")));

        
        scheduler.start();
    }
}

SchedulerListener

  • SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用,与Scheduler有关的事件:增加一个Job/trigger、删除一个Job/trigger、scheduler发生错误、关闭scheduler等

    public class MySchedulerListener implements SchedulerListener {

    public void jobScheduled(Trigger trigger) {
        String name = trigger.getKey().getName();
    

    // 部署JobDetail是调用
    System.out.println(name+ " 完成部署");
    }

    public void jobUnscheduled(TriggerKey triggerKey) {
        String name = triggerKey.getName();
    

    // 卸载JobDetail是调用
    System.out.println(name+ " 完成卸载");
    }

    public void triggerFinalized(Trigger trigger) {
        String name = trigger.getKey().getName();
        System.out.println(name+" 被移除");
    }
    
    public void triggerPaused(TriggerKey triggerKey) {
        String name = triggerKey.getName();
        System.out.println(name+ " 正在被暂停");
    }
    
    public void triggersPaused(String s) {
        System.out.println(s+"组 正在被暂停");
    }
    
    public void triggerResumed(TriggerKey triggerKey) {
        String name = triggerKey.getName();
        System.out.println(name+ "正在从暂停中恢复");
    }
    
    public void triggersResumed(String s) {
        System.out.println(s+ "组  正在从暂停中恢复");
    }
    
    public void jobAdded(JobDetail jobDetail) {
        System.out.println(jobDetail.getKey().getName()+"添加工作任务");
    }
    
    public void jobDeleted(JobKey jobKey) {
        System.out.println(jobKey.getName() +"添加工作任务");
    }
    
    public void jobPaused(JobKey jobKey) {
        System.out.println(jobKey.getName() +"暂停工作任务");
    }
    
    public void jobsPaused(String s) {
        System.out.println(s+" 组  暂停工作任务");
    }
    
    public void jobResumed(JobKey jobKey) {
        System.out.println(jobKey.getName() +"恢复工作任务");
    }
    
    public void jobsResumed(String s) {
        System.out.println(s+" 组  恢复工作任务");
    }
    
    public void schedulerError(String s, SchedulerException e) {
    
    }
    
    public void schedulerInStandbyMode() {
    
    }
    
    public void schedulerStarted() {
    
    }
    
    public void schedulerStarting() {
    
    }
    
    public void schedulerShutdown() {
    
    }
    
    public void schedulerShuttingdown() {
    
    }
    
    public void schedulingDataCleared() {
    
    }
    

    }

    
    
  • public class HelloSchedulerListenerDemo {
        public static void main(String[] args) throws SchedulerException {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    
            Date startDate = new Date();
    
    
            //任务实例JobBulider
            JobDetail jobDetail = JobBuilder.newJob(HelloJobSimple.class)
                    .withIdentity("job1","group1")
                    .usingJobData("message","打印日志")
                    .build();
    
            //触发器Trigger
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1","group1")
                    .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))//每5秒执行一次,只执行4次从 0开始
                    .build();
    
            //让调度器去关联触发器,保证触发器定义的条件执行任务
            scheduler.scheduleJob(jobDetail,trigger);
    
    //        创建调度器监听
            scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());
            scheduler.start();
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值