任务调度之Quartz(一):Quartz基本使用

一、Quartz基本介绍

       Quatz 是一个特性丰富的,开源的任务调度库,它几乎可以嵌入所有的 Java 程序,从

       很小的独立应用程序到大型商业系统。Quartz 可以用来创建成百上千的简单的或者复杂

       的任务,这些任务可以用来执行任何程序可以做的事情。Quartz 拥有很多企业级的特性,

       包括支持 JTA 事务和集群。

二、Quartz基本使用

1、导入依赖

      Quartz使用前需要引入Quartz的依赖,如下所示:

       <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>

2、Quartz 默认配置文件

      在Quartz依赖中的 org.quarzt 包路径下有个配置文件 quartz.properties,该配置问价

      是 Quartz 的默认配置文件,若在自己的项目中创建了同名的配置文件,即在自己的项目

      中存在名称是 quartz.properties 的配置文件,则自定义的 quartz.properties 将覆盖 org.quarzt

      包路径的配置文件quartz.properties,

      默认配置文件如下所示:

org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

//配置保存Quartz 运行数据的方式,RAMJobStore 表示Quartz 运行数据保存在内存中,
//保存在内存中的数据当项目重启时数据会丢失
//为了Quartz 运行数据持有化,可以将Quartz 运行数据保存到磁盘中,如保存在数据库中
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

/**
  JobStore持久化配置:将Quartz的数据保存到数据库中的配置
*/
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 使用quartz.properties,不使用默认配置
org.quartz.jobStore.useProperties:true
#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:QRTZ_
org.quartz.jobStore.dataSource:myDS

#配置数据源
org.quartz.dataSource.myDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL:jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.myDS.user:root
org.quartz.dataSource.myDS.password:123456
org.quartz.dataSource.myDS.validationQuery=select 0 from dual

     

3、创建Job

      Job是Quartz执行的具体个体对象;Job创建也很简单,只需要让自己定义的类实现Quartz

      中的Job接口,并实现接口方法execute();

      execute() 方法中执行自己需求中需要调度执行的具体业务逻辑,即具体的任务内容;

      示例代码如下:

/*******************************************************
 * 创建Job,job需要实现 quartz 中的job接口,并实现execute() 方法;
 * execute() 方法中执行自己需求中需要调度执行的具体业务逻辑,即具体的任务内容
 *
 * @author lbf
 * 
 *******************************************************/
public class QuartzJob01 implements Job {

    /**
     *
     * @param context  Quartz执行任务job时的上下文对象,通过该上下文对象可以获取JobDetail 设置的数据
     * @throws JobExecutionException
     */
    public void execute(JobExecutionContext context) throws JobExecutionException {

        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //获取 JobDetail 包装Job时设置的数据集合 JobDataMap
        //JobDataMap 通过map 的k-v 的方式保存数据
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        System.out.println( " " + sf.format(date) + " 任务1执行了," + dataMap.getString("msb"));

    }
}

      注意:

             在Quartz 中Job并不能直接执行,需要把Job包装成JobDetail 后,才能被执行;

             JobDetail中有个JobDataMap 类型的属性,可以把它看作一个一个Map,其以

             key-value的形式保存JobDetail 动态设置的属性数据。

4、创建Trigger

      触发器 Trigger,用于定义任务Job出发执行的规律

5、创建Scheduler     

      调度器  Scheduler 主要用于将 JobDetail 和 Trigger绑定,并注册到容器中。

      JobDetail 和 Trigger绑定是“一对多”的关系(1:N),即一个JobDetail可以去绑定多

      个触发器Trigger;

       Scheduler 先启动后启动无所谓,只要有 Trigger 到达触发条件,就会执行任务。

       Scheduler 是单例的

步骤4、5示例代码如下:

/*******************************************************
 * 执行任务
 *
 * @author lbf
 * 
 *******************************************************/
public class MyScheduler {
    public static void main(String[] args) throws SchedulerException {

        /**
         * 将任务 QuartzJob01 包装成一个JobDetail
         * withIdentity: 用于设置JobDetail 的唯一标识
         * usingJobData:用于给 JobDetail 设置参数数据,该数据以k-v的形式保存在 JobDataMap中,用于扩展调度任务执行时的属性
         *              ,该数据可以Job的execute 方法中通过上下文对象 JobExecutionContext 获取
         *
         */
        JobDetail jobDetail = JobBuilder.newJob(QuartzJob01.class)
                .withIdentity("job02","grop01")
                .usingJobData("msb","haha-java")
                .usingJobData("intType",123)
                .build();

        //创建触发器
        //基于 SimpleTrigger 定义了一个每 2 秒钟运行一次、不断重复的 Trigger:
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger01","group01")//设置Trigger 的唯一标识
                .startNow() //设置Trigger 立即启动
                .withSchedule(
                        SimpleScheduleBuilder.simpleSchedule() //
                                .withIntervalInSeconds(2) //设置任务每隔2s执行一次
                                .repeatForever()
                )
                .build();

        /**
         * 创建调度器
         */
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        /**
         * 通过调度器绑定 JobDetail和触发器 Trigger,绑定关系是:1:N,即一个JobDetail可以去绑定多个触发器Trigger
         *
         */
        scheduler.scheduleJob(jobDetail,trigger);
        //启动调度器
        //Scheduler 先启动后启动无所谓,只要有 Trigger 到达触发条件,就会执行任务。
        scheduler.start();
    }
}

6、Listener

     Quartz 中提供了3种监听器,即 JobListener、TriggerListener、SchedulerListener分

     别用来监听 Job、Trigger 和 Scheduler 的运行情况;下边来分别看下这3种监听器的

     使用。

6.1、JobListener

        JobListener 主要用于监听 JobDetail(即Job) 在运行过程中是否有关键事件发生;

        这些关键事件包括:JobDetail是否被Trigger否决、JobDetail 是否执行完成等。

        JobListener示例代码如下:

/*******************************************************
 * 创建Job监听器,用于监听Job 任务的执行情况,
 * Job监听器需要实现接口 JobListener 就可以了
 * @author lbf
 * @date 2024-12-01 11:07
 *******************************************************/
public class MyJobListener implements JobListener {

    /**
     * 返回监听器的名称
     * @return
     */
    public String getName() {
        String name = getClass().getSimpleName();
        System.out.println( "【JobListener】 :"+ "获取到监听器名称:"+name);
        return name;
    }

    /**
     * 调度器Scheduler 在即将执行 JobDetail 时执行这个方法
     *
     * @param jobExecutionContext Job执行时的上下文对象
     */
    public void jobToBeExecuted(JobExecutionContext context) {

        //获取任务名称
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("【JobListener】 :"+ jobName + " ——任务即将执行 ");
    }

    /**
     * 调度器 Scheduler 在 JobDetail 即将被执行,但又被 TriggerListener 否决了时调用这个方法
     *
     * @param jobExecutionContext
     */
    public void jobExecutionVetoed(JobExecutionContext context) {

        //获取任务名称
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("【JobListener】 :"+ jobName + " ——任务被TriggerListener否决  ");
    }

    /**
     * 调度器 Scheduler 在 JobDetail 被执行之后调用这个方法
     * @param jobExecutionContext
     * @param e
     */
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException e) {

        //获取任务名称
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("【JobListener】 :"+ jobName + " ——任务执行完成  ");
    }
}


/*******************************************************
 * MyJobListener测试
 * @author lbf
 * @date 2024-12-01 11:19
 *******************************************************/
public class MyJobListenerTest {

    public static void main(String[] args) throws SchedulerException {
        // JobDetail
        JobDetail jobDetail = JobBuilder.newJob(QuartzJob01.class).withIdentity("job1", "group1").build();

        // Trigger
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();

        // SchedulerFactory
        SchedulerFactory  factory = new StdSchedulerFactory();

        // Scheduler
        Scheduler scheduler = factory.getScheduler();

        scheduler.scheduleJob(jobDetail, trigger);

        //注册一个全局的Job Listener
        //监听器由 ListenerManager 管理
        //todo 注意:监听器要在最后边添加
        scheduler.getListenerManager().addJobListener(new MyJobListener(), EverythingMatcher.allJobs());

        scheduler.start();
    }
}

  

6.2、TriggerListener

         TriggerListener 主要被用来监听触发器Trigger是否被触发,及触发后Job的execute 方法

         是否被执行

         TriggerListener 示例代码如下:

/*******************************************************
 * 触发器监听器
 * @author lbf
 * @date 2024-12-01 16:40
 *******************************************************/
public class MyTriggerListener implements TriggerListener {

    private String name;

    public MyTriggerListener(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    // Trigger 被触发,Job 上的 execute() 方法将要被执行时
    public void triggerFired(Trigger trigger, JobExecutionContext context) {
        String triggerName = trigger.getKey().getName();
        System.out.println("Method 11111 " + triggerName + " was fired");
    }

    // 在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法
    // 返回true时,这个任务不会被触发
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
        String triggerName = trigger.getKey().getName();
        System.out.println("Method 222222 " + triggerName + " was not vetoed");
        return false;
    }

    //Trigger 错过触发时调用
    public void triggerMisfired(Trigger trigger) {
        String triggerName = trigger.getKey().getName();
        System.out.println("Method 333333 " + triggerName + " misfired");
    }

    //Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法
    public void triggerComplete(Trigger trigger, JobExecutionContext context,
                                Trigger.CompletedExecutionInstruction triggerInstructionCode) {
        String triggerName = trigger.getKey().getName();
        System.out.println("Method 444444 " + triggerName + " is complete");
        System.out.println("------------");
    }
}




/*******************************************************
 *
 * @author lbf
 * @date 2024-12-01 17:10
 *******************************************************/
public class MyTriggerListenerTest {

    public static void main(String[] args) throws SchedulerException {

        // JobDetail
        JobDetail jobDetail = JobBuilder.newJob(QuartzJob01.class).withIdentity("job1", "group1").build();

        // Trigger
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever()).build();

        // SchedulerFactory
        SchedulerFactory  factory = new StdSchedulerFactory();

        // Scheduler
        Scheduler scheduler = factory.getScheduler();

        scheduler.scheduleJob(jobDetail, trigger);


        // 创建并注册一个全局的Trigger Listener
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("myListener1"), EverythingMatcher.allTriggers());

        // 创建并注册一个局部的Trigger Listener
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("myListener2"), KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger1", "gourp1")));

        // 创建并注册一个特定组的Trigger Listener
        GroupMatcher<TriggerKey> matcher = GroupMatcher.triggerGroupEquals("gourp1");
        scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("myListener3"), matcher);

        scheduler.start();

    }
}

6.3、SchedulerListener

        SchedulerListener主要用于监控 Scheduler 的生命周期中是否有关键事件发生,

        当 Scheduler 有关键事件发生时 SchedulerListener 会被调用

        与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler

        运行时发送错误,关闭scheduler等。

       SchedulerListener示例代码如下:

       

/*******************************************************
 * 调度器监听器
 * 该监听器需要实现接口 SchedulerListener
 *
 * SchedulerListener主要用于监控 Scheduler 的生命周期中是否有关键事件发生,当 Scheduler 有关键事件发生时 SchedulerListener 会被调用
 * 与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler发生错误,关闭scheduler等。
 *
 * @author lbf
 * @date 2024-12-01 17:20
 *******************************************************/
public class MySchedulerListener implements SchedulerListener {

    /**
     * 部署 JobDetail 时调用
     * @param trigger
     */
    public void jobScheduled(Trigger trigger) {
        String jobName = trigger.getJobKey().getName();
        System.out.println(jobName + " has been scheduled");
    }

    /**
     * 卸载 JobDetail 时调用
     *
     * @param triggerKey
     */
    public void jobUnscheduled(TriggerKey triggerKey) {
        System.out.println(triggerKey + " is being unscheduled");
    }

    /**
     * 当一个 Trigger的job执行完成再也不会触发的时调用这个方法;
     * 此时该 Trigger会被删除(除非该Trigger被持久化到磁盘)
     *
     * @param trigger
     */
    public void triggerFinalized(Trigger trigger) {
        System.out.println("Trigger is finished for " + trigger.getJobKey().getName());
    }

    /**
     * 当一个 Trigger 被暂停时调用该方法
     * @param triggerKey
     */
    public void triggerPaused(TriggerKey triggerKey) {
        System.out.println(triggerKey + " is being paused");
    }

    /**
     * 当一个 Trigger组 被暂停时调用该方法
     * @param triggerGroup
     */
    public void triggersPaused(String triggerGroup) {
        System.out.println("trigger group " + triggerGroup + " is being paused");
    }

    /**
     * 当一个 Trigger 从暂停中恢复时调用该方法
     *
     * @param triggerKey
     */
    public void triggerResumed(TriggerKey triggerKey) {
        System.out.println(triggerKey + " is being resumed");
    }

    /**
     * 当一个 Trigger组 从暂停中恢复时调用该方法
     * @param triggerGroup
     */
    public void triggersResumed(String triggerGroup) {
        System.out.println("trigger group " + triggerGroup + " is being resumed");
    }


    /**
     * 当一个 JobDetail 任务被添加时调用该方法
     * @param jobDetail
     */
    public void jobAdded(JobDetail jobDetail) {
        System.out.println(jobDetail.getKey() + " is added");
    }

    /**
     * 当一个 JobDetail 任务被删除时调用该方法
     * @param jobKey
     */
    public void jobDeleted(JobKey jobKey) {
        System.out.println(jobKey + " is deleted");
    }

    /**
     * 当一个 JobDetail 任务被暂停时调用该方法
     * @param jobKey
     */
    public void jobPaused(JobKey jobKey) {
        System.out.println(jobKey + " is paused");
    }

    /**
     * 当一组 JobDetail 任务被暂停时调用该方法
     * @param jobGroup
     */
    public void jobsPaused(String jobGroup) {
        System.out.println("job group " + jobGroup + " is paused");
    }

    /**
     * 当一个 JobDetail 任务从暂停中恢复时调用该方法
     * @param jobKey
     */
    public void jobResumed(JobKey jobKey) {
        System.out.println(jobKey + " is resumed");
    }

    /**
     * 当一组 JobDetail 任务从暂停中恢复时调用该方法
     * @param jobGroup
     */
    public void jobsResumed(String jobGroup) {
        System.out.println("job group " + jobGroup + " is resumed");
    }

    /**
     * 在调度器 Scheduler 运行时出现错误时调用该方法
     * @param msg
     * @param cause
     */
    public void schedulerError(String msg, SchedulerException cause) {
        System.out.println(msg + cause.getUnderlyingException().getStackTrace());
    }

    /**
     *  当Scheduler处于StandBy模式时,调用该方法
     */
    public void schedulerInStandbyMode() {
        System.out.println("scheduler is in standby mode");
    }

    /**
     *  当Scheduler启动时,调用该方法
     */
    public void schedulerStarted() {
        System.out.println("scheduler has been started");
    }


    public void schedulerStarting() {
        System.out.println("scheduler is being started");
    }

    /**
     * 当 Scheduler停止时时,调用该方法
     */
    public void schedulerShutdown() {
        System.out.println("scheduler has been shutdown");
    }

    public void schedulerShuttingdown() {
        System.out.println("scheduler is being shutdown");
    }

    /**
     * 当 Scheduler中的数据被清除时,调用该方法。
     */
    public void schedulingDataCleared() {
        System.out.println("scheduler has cleared all data");
    }
}





/*******************************************************
 * 调度器监听器练习
 *
 * @author lbf
 * @date 2024-12-01 17:55
 *******************************************************/
public class MySchedulerListenerTest {

    public static void main(String[] args) throws SchedulerException {

        // JobDetail
        JobDetail jobDetail = JobBuilder.newJob(QuartzJob01.class).withIdentity("job1", "group1").build();

        // Trigger
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();

        // SchedulerFactory
        SchedulerFactory  factory = new StdSchedulerFactory();

        // Scheduler
        Scheduler scheduler = factory.getScheduler();

        scheduler.scheduleJob(jobDetail, trigger);

        // 注册Scheduler Listener
        scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());

        scheduler.start();

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值