首页 > 其他分享 >【SpringBoot】调度和执行定时任务--Quartz(超详细)

【SpringBoot】调度和执行定时任务--Quartz(超详细)

时间:2024-09-14 21:50:59浏览次数:13  
标签:Quartz SpringBoot -- 任务 Job quartz import org public

Quartz 是一个功能强大的任务调度框架,广泛用于在 Java 应用程序中定时执行任务,同时它支持 Cron 表达式、持久化任务、集群等特性。以下是 Quartz 的详细使用教程,包括安装、基本概念、简单示例和高级功能。

1. 安装 Quartz

首先,在你的项目中添加 Quartz 依赖。对于 Maven 项目,可以在 pom.xml 中添加以下依赖:

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

对于 Gradle 项目,可以在 build.gradle 中添加以下依赖:

implementation 'org.quartz-scheduler:quartz:2.3.2'

2. 基本概念

Quartz 的核心概念包括:

  • Scheduler:调度器,是 Quartz 的核心,负责管理和调度任务。
  • Job:任务,是实际执行的工作单元。需要实现 Job 接口。
  • JobDetail:定义任务的详细信息,包括任务的名称、组、以及任务的类。
  • Trigger:触发器,定义任务何时执行。常用的触发器包括 SimpleTrigger 和 CronTrigger。
  • JobStore:任务存储,定义任务的存储方式。常见的有 RAMJobStore(内存存储)和 JDBCJobStore(数据库存储)。

3. 简单示例

以下是一个简单的 Quartz 示例,展示如何创建和调度一个任务。

1. 定义 Job 类

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Hello, Quartz! Current time: " + System.currentTimeMillis());
    }
}

2. 配置 Scheduler 和 Job

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzExample {
    public static void main(String[] args) throws SchedulerException {
        // 创建 Scheduler 实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 定义一个 JobDetail 实例
        JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("helloJob", "group1")
                .build();

        // 创建一个触发器,每隔5秒执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("helloTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(5)
                        .repeatForever())
                .build();

        // 调度任务
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

4. 高级功能

1. 使用 CronTrigger

CronTrigger 允许使用 Cron 表达式来定义复杂的调度规则。

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class CronTriggerExample {
    public static void main(String[] args) throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("cronJob", "group1")
                .build();

        // 使用 Cron 表达式创建触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("cronTrigger", "group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
                .build();

        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

2. Cron 表达式

Cron 表达式用于定义任务调度的时间规则。它由6或7个字段组成,字段之间用空格分隔。以下是每个字段的含义:

┌───────────── 秒 (0 - 59)
│ ┌───────────── 分 (0 - 59)
│ │ ┌───────────── 小时 (0 - 23)
│ │ │ ┌───────────── 日 (1 - 31)
│ │ │ │ ┌───────────── 月 (1 - 12)
│ │ │ │ │ ┌───────────── 星期几 (0 - 7) (0 和 7 都是星期日)
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * *

2.1 特殊字符

  • *: 表示任意值。
  • ?: 仅在日和星期字段中使用,表示不指定值。
  • -: 表示范围,例如 10-12 表示从10到12。
  • ,: 表示列表值,例如 1,2,3 表示1、2、3。
  • /: 表示增量,例如 0/15 表示从0开始每15分钟。
  • L: 表示最后,例如 L 在日字段表示月的最后一天。
  • W: 表示最近的工作日,例如 15W 表示最接近15号的工作日。
  • #: 表示第几个星期几,例如 2#1 表示第一个星期一。

2.2 示例

  • 0 0 12 * * ?: 每天中午12点执行。
  • 0 15 10 ? * *: 每天上午10:15执行。
  • 0 15 10 * * ?: 每天上午10:15执行。
  • 0 15 10 * * ? 2024: 2024年每天上午10:15执行。
  • 0 * 14 * * ?: 每天下午2点到2:59每分钟执行一次。
  • 0 0/5 14 * * ?: 每天下午2点到2:55每5分钟执行一次。
  • 0 0/5 14,18 * * ?: 每天下午2点到2:55每5分钟执行一次,以及每天下午6点到6:55每5分钟执行一次。
  • 0 0-5 14 * * ?: 每天下午2点到2:05每分钟执行一次。
  • 0 10,44 14 ? 3 WED: 每年三月的每个星期三下午2:10和2:44执行。

3. 使用 JobListener

JobListener 可以在任务执行的不同阶段进行拦截和处理。

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;

public class MyJobListener implements JobListener {
    @Override
    public String getName() {
        return "MyJobListener";
    }
    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
      //在任务即将被执行时调用,可以在任务执行前进行一些准备工作或记录日志。
        System.out.println("Job is about to be executed: " + context.getJobDetail().getKey());
    }
    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
      //在任务执行被否决时调用,当某些条件满足时,可以阻止任务的执行,并在此方法中执行相应的处理逻辑。
        System.out.println("Job execution was vetoed: " + context.getJobDetail().getKey());
    }
    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
      //在任务执行完成后调用,可以在任务执行后进行一些清理工作或记录日志。如果任务执行过程中抛出异常,jobException 将包含该异常信息。
        System.out.println("Job was executed: " + context.getJobDetail().getKey());
        if (jobException != null) {
            System.out.println("Job encountered an exception: " + jobException.getMessage());
        }
    }
}

在 Scheduler 中注册 JobListener:

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class JobListenerExample {
    public static void main(String[] args) throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
      //创建任务
        JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("listenerJob", "group1")
                .build();
      创建触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("listenerTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(5)
                        .repeatForever())
                .build();

        // 创建并注册 JobListener
        MyJobListener listener = new MyJobListener();
        scheduler.getListenerManager().addJobListener(listener);

        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

5. 持久化支持

Quartz 支持将任务数据持久化到数据库中,以便在系统重启后恢复任务状态。可以使用 JDBCJobStore 来实现这一点。

quartz.properties 文件中配置 JDBCJobStore:

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.dataSource.myDS.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/quartz
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = password
org.quartz.dataSource.myDS.maxConnections = 5

6. 并发控制

在 Quartz 中,默认情况下,任务是并发执行的。如果需要确保同一个任务实例不被并发执行,可以实现 DisallowConcurrentExecution 接口。为了清楚地展示 DisallowConcurrentExecution 注解的作用,我们可以创建两个示例:一个使用 DisallowConcurrentExecution 注解,另一个不使用该注解。通过这两个示例,我们可以观察到任务在并发执行方面的差异。

示例 1:不使用 DisallowConcurrentExecution

在这个示例中,我们创建一个简单的任务类,它会模拟一个长时间运行的任务,并且不使用 DisallowConcurrentExecution 注解。

1. 定义 Job 类

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class ConcurrentJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("ConcurrentJob is executing at: " + System.currentTimeMillis());
        try {
            // 模拟长时间运行的任务
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("ConcurrentJob finished at: " + System.currentTimeMillis());
    }
}

2. 配置 Scheduler 和 Job

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class ConcurrentJobExample {
    public static void main(String[] args) throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        JobDetail job = JobBuilder.newJob(ConcurrentJob.class)
                .withIdentity("concurrentJob", "group1")
                .build();

        // 创建一个触发器,每隔2秒执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("concurrentTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(2)
                        .repeatForever())
                .build();

        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

示例 2:使用 DisallowConcurrentExecution

在这个示例中,我们创建一个类似的任务类,但这次使用 DisallowConcurrentExecution 注解,确保任务不会并发执行。

1. 定义 Job 类

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution
public class NonConcurrentJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("NonConcurrentJob is executing at: " + System.currentTimeMillis());
        try {
            // 模拟长时间运行的任务
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("NonConcurrentJob finished at: " + System.currentTimeMillis());
    }
}

2. 配置 Scheduler 和 Job

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class NonConcurrentJobExample {
    public static void main(String[] args) throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        JobDetail job = JobBuilder.newJob(NonConcurrentJob.class)
                .withIdentity("nonConcurrentJob", "group1")
                .build();

        // 创建一个触发器,每隔2秒执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("nonConcurrentTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(2)
                        .repeatForever())
                .build();

        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

运行示例

当你运行这两个示例时,你会看到以下行为:

不使用 DisallowConcurrentExecution 的输出

ConcurrentJob is executing at: 1633017600000
ConcurrentJob is executing at: 1633017602000
ConcurrentJob finished at: 1633017605000
ConcurrentJob is executing at: 1633017604000
ConcurrentJob finished at: 1633017607000
ConcurrentJob finished at: 1633017609000

可以看到,任务是并发执行的,多个任务实例同时运行。

使用 DisallowConcurrentExecution 的输出

NonConcurrentJob is executing at: 1633017600000
NonConcurrentJob finished at: 1633017605000
NonConcurrentJob is executing at: 1633017605000
NonConcurrentJob finished at: 1633017610000
NonConcurrentJob is executing at: 1633017610000
NonConcurrentJob finished at: 1633017615000

可以看到,任务是顺序执行的,新的任务实例只有在前一个实例完成后才会开始执行。

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution
public class NonConcurrentJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Non-concurrent job is executing at: " + System.currentTimeMillis());
    }
}

通过这两个示例,我们可以清楚地看到 DisallowConcurrentExecution 注解的作用:它确保同一个任务实例不会并发执行,而是顺序执行。这在某些需要严格控制任务执行顺序的场景中非常有用。

7. 任务依赖管理

Quartz 本身并不直接支持任务依赖管理(即任务之间的依赖关系),但可以通过编程方式实现这一功能。通常的方法是使用多个 Job 和 Trigger,并在 Job 执行完成后手动调度下一个依赖的 Job。

1. 异步任务依赖管理

Quartz 本身并不直接支持任务依赖管理(即任务之间的依赖关系),但可以通过编程方式实现这一功能。通常的方法是使用多个 Job 和 Trigger,并在 Job 执行完成后手动调度下一个依赖的 Job。

以下是一个示例,展示如何在 Quartz 中实现任务依赖管理:

示例场景

假设有三个任务:

  1. 任务 A:完成后触发任务 B。
  2. 任务 B:完成后触发任务 C。
  3. 任务 C:最后执行。

实现步骤

  1. 定义三个 Job 类。
  2. 配置 Scheduler 和 Job。
  3. 在每个 Job 中执行完成后手动调度下一个依赖的 Job。

代码示例

1. 定义 Job 类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class JobA implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job A executed at: " + System.currentTimeMillis());

        // 获取 Scheduler 实例
        Scheduler scheduler = context.getScheduler();
        try {
            // 创建 JobB 的 JobDetail
            JobDetail jobB = JobBuilder.newJob(JobB.class)
                    .withIdentity("jobB", "group1")
                    .build();

            // 创建立即触发的 Trigger
            Trigger triggerB = TriggerBuilder.newTrigger()
                    .withIdentity("triggerB", "group1")
                    .startNow()
                    .build();

            // 调度 JobB
            scheduler.scheduleJob(jobB, triggerB);
        } catch (SchedulerException e) {
            throw new JobExecutionException(e);
        }
    }
}

public class JobB implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job B executed at: " + System.currentTimeMillis());

        // 获取 Scheduler 实例
        Scheduler scheduler = context.getScheduler();
        try {
            // 创建 JobC 的 JobDetail
            JobDetail jobC = JobBuilder.newJob(JobC.class)
                    .withIdentity("jobC", "group1")
                    .build();

            // 创建立即触发的 Trigger
            Trigger triggerC = TriggerBuilder.newTrigger()
                    .withIdentity("triggerC", "group1")
                    .startNow()
                    .build();

            // 调度 JobC
            scheduler.scheduleJob(jobC, triggerC);
        } catch (SchedulerException e) {
            throw new JobExecutionException(e);
        }
    }
}

public class JobC implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job C executed at: " + System.currentTimeMillis());
    }
}
2. 配置 Scheduler 和 Job
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzDependencyExample {
    public static void main(String[] args) throws SchedulerException {
        // 创建 Scheduler 实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 定义 JobA
        JobDetail jobA = JobBuilder.newJob(JobA.class)
                .withIdentity("jobA", "group1")
                .build();

        // 创建立即触发的 Trigger
        Trigger triggerA = TriggerBuilder.newTrigger()
                .withIdentity("triggerA", "group1")
                .startNow()
                .build();

        // 调度 JobA
        scheduler.start();
        scheduler.scheduleJob(jobA, triggerA);
    }
}

解释

  1. JobA:在执行完成后,手动调度 JobB
  2. JobB:在执行完成后,手动调度 JobC
  3. JobC:最后执行,没有后续任务。

通过这种方式,可以实现任务之间的依赖关系。在每个任务执行完成后,手动调度下一个依赖的任务。这样,即使 Quartz 本身不直接支持任务依赖管理,也可以通过编程方式实现这一功能。

注意事项

  1. 异常处理:确保在调度下一个任务时正确处理异常,防止由于调度失败导致任务链中断。
  2. 并发控制:如果有多个任务链,需要确保并发控制,防止多个任务同时调度同一个任务。
  3. 持久化支持:如果任务链较长或需要持久化,确保使用持久化的 Scheduler 配置,以便在系统重启后恢复任务状态。

2. 同步任务依赖管理

在上面的示例中,任务之间的调度是异步的。每个 Job 在执行完成后,会立即调度下一个 Job,但不会等待下一个 Job 的执行完成。这种方式适用于大多数场景,但如果需要同步执行(即一个任务必须等待前一个任务执行完成后再执行),则需要一些额外的机制来确保任务的同步执行。

为了实现同步的任务依赖管理,可以使用以下方法:

  1. 使用 JobListener:监听每个任务的执行完成事件,并在事件触发时调度下一个任务。
  2. 使用共享的状态或信号量:在任务之间共享状态或使用信号量来确保任务按顺序执行。

以下是一个使用 JobListener 实现同步任务依赖管理的示例:

实现步骤

  1. 定义三个 Job 类。
  2. 实现 JobListener接口。
  3. 配置 Scheduler 和 Job。
  4. 当触发jobWasExecuted后调度下一个依赖的 Job。

示例代码

1. 定义 Job 类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class JobA implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job A executed at: " + System.currentTimeMillis());
    }
}

public class JobB implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job B executed at: " + System.currentTimeMillis());
    }
}

public class JobC implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Job C executed at: " + System.currentTimeMillis());
    }
}
2. 定义 JobListener
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.quartz.SchedulerException;

public class DependencyJobListener implements JobListener {

    private Scheduler scheduler;

    public DependencyJobListener(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    @Override
    public String getName() {
        return "DependencyJobListener";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        // No action needed before job execution
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        // No action needed if job execution is vetoed
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        String jobName = context.getJobDetail().getKey().getName();
        try {
            if ("jobA".equals(jobName)) {
                // 调度 JobB
                JobDetail jobB = JobBuilder.newJob(JobB.class)
                        .withIdentity("jobB", "group1")
                        .build();

                Trigger triggerB = TriggerBuilder.newTrigger()
                        .withIdentity("triggerB", "group1")
                        .startNow()
                        .build();

                scheduler.scheduleJob(jobB, triggerB);
            } else if ("jobB".equals(jobName)) {
                // 调度 JobC
                JobDetail jobC = JobBuilder.newJob(JobC.class)
                        .withIdentity("jobC", "group1")
                        .build();

                Trigger triggerC = TriggerBuilder.newTrigger()
                        .withIdentity("triggerC", "group1")
                        .startNow()
                        .build();

                scheduler.scheduleJob(jobC, triggerC);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}
3. 配置 Scheduler 和 Job
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzDependencyExample {
    public static void main(String[] args) throws SchedulerException {
        // 创建 Scheduler 实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 定义 JobA
        JobDetail jobA = JobBuilder.newJob(JobA.class)
                .withIdentity("jobA", "group1")
                .build();

        // 创建立即触发的 Trigger
        Trigger triggerA = TriggerBuilder.newTrigger()
                .withIdentity("triggerA", "group1")
                .startNow()
                .build();

        // 添加 JobListener
        scheduler.getListenerManager().addJobListener(new DependencyJobListener(scheduler));

        // 调度 JobA
        scheduler.start();
        scheduler.scheduleJob(jobA, triggerA);
    }
}

解释

  1. JobA、JobB、JobC:分别定义三个独立的 Job 类。
  2. DependencyJobListener:实现 JobListener 接口,在每个 Job 执行完成后,根据当前执行的 Job 调度下一个 Job。
  3. Scheduler 配置:在 Scheduler 中注册 DependencyJobListener,并调度初始的 JobA。

注意事项

  1. 异常处理:确保在调度下一个任务时正确处理异常,防止由于调度失败导致任务链中断。
  2. 并发控制:如果有多个任务链,需要确保并发控制,防止多个任务同时调度同一个任务。
  3. 持久化支持:如果任务链较长或需要持久化,确保使用持久化的 Scheduler 配置,以便在系统重启后恢复任务状态。

3. 任务拦截

在 Quartz 中,可以通过实现 JobListener 来拦截任务的执行。JobListener 提供了几个方法,可以在任务执行前、执行后以及任务被否决时进行拦截和处理。

下面是一个详细的示例代码,展示如何使用 JobListener 来拦截任务的执行,并附有详细注释。

示例代码

1. 定义 Job 类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

// 定义一个简单的 Job 类
public class SampleJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("SampleJob is executing at: " + System.currentTimeMillis());
    }
}
2. 实现 JobListener
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;

// 实现 JobListener 接口
public class MyJobListener implements JobListener {

    @Override
    public String getName() {
        // 返回监听器的名称
        return "MyJobListener";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        // 在任务即将执行时调用
        System.out.println("Job is about to be executed: " + context.getJobDetail().getKey());
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        // 在任务被否决时调用
        System.out.println("Job execution was vetoed: " + context.getJobDetail().getKey());
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        // 在任务执行完成后调用
        System.out.println("Job was executed: " + context.getJobDetail().getKey());
        if (jobException != null) {
            System.out.println("Job encountered an exception: " + jobException.getMessage());
        }
    }
}
3. 配置 Scheduler 和 Job
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzJobListenerExample {
    public static void main(String[] args) throws SchedulerException {
        // 创建 Scheduler 实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 定义一个 JobDetail 实例
        JobDetail job = JobBuilder.newJob(SampleJob.class)
                .withIdentity("sampleJob", "group1")
                .build();

        // 创建一个触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("sampleTrigger", "group1")
                .startNow()
                .build();

        // 创建并注册 JobListener
        MyJobListener listener = new MyJobListener();
        scheduler.getListenerManager().addJobListener(listener);

        // 调度任务
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

解释

  1. SampleJob:定义一个简单的 Job 类,包含一个 execute 方法,打印当前时间。
  2. MyJobListener:实现 JobListener 接口,提供四个方法:
    • getName:返回监听器的名称。
    • jobToBeExecuted:在任务即将执行时调用,打印任务的 Key。
    • jobExecutionVetoed:在任务被否决时调用,打印任务的 Key。
    • jobWasExecuted:在任务执行完成后调用,打印任务的 Key 和异常信息(如果有)。
  3. QuartzJobListenerExample:主类,配置 Scheduler 和 Job:
    • 创建 Scheduler 实例。
    • 定义一个 JobDetail 实例。
    • 创建一个触发器。
    • 创建并注册 JobListener 实例。
    • 调度任务并启动 Scheduler。

注意事项

  1. 异常处理:在 jobWasExecuted 方法中处理任务执行中的异常,确保异常信息被记录或处理。
  2. 并发控制:如果有多个任务并发执行,需要确保监听器的实现是线程安全的。
  3. 持久化支持:在需要持久化任务状态时,确保 Scheduler 配置支持持久化。

标签:Quartz,SpringBoot,--,任务,Job,quartz,import,org,public
From: https://blog.csdn.net/qq_45687669/article/details/142264340

相关文章

  • 【视频讲解】线性时间序列原理及混合ARIMA-LSTM神经网络模型预测股票收盘价研究实例
    原文链接:https://tecdat.cn/?p=37702 原文出处:拓端数据部落公众号 分析师:DongzhiZhang 近年来人工神经网络被学者们应用十分广泛,预测领域随着神经网络的引入得到了很大的发展。本文认为单一神经网络模型对序列所包含的线性信息和非线性信息的挖掘是有限的,因此本文为了进一......
  • 实战13-搜索模块滑动效果01
    import{getHomeDataApi}from'../api/home';import{BannerListDataSource,INavList,IPlanList,ITitleList}from'../api/models/HomeData';importSwiperLayoutfrom'../views/Home/SwiperLayout';import{window}from'......
  • 利士策分享,细品礼仪之美:在日常中优雅相处的艺术
    利士策分享,细品礼仪之美:在日常中优雅相处的艺术在当今这个快节奏、高压力的社会里,人与人之间的交往似乎被简化成了快餐式的信息交流。然而,根植于文化深处的礼仪之花,依然是促进社会和谐、深化人际关系的宝贵财富。它不仅是对他人的尊重,更是个人修养的展现。以下,我们将探......
  • 利士策分享:探索适宜娱乐,实现心灵宁静与成长
    利士策分享:探索适宜娱乐,实现心灵宁静与成长在探讨如何找到并实践适宜的娱乐方式时,我们可以从以下几个方面入手,结合具体建议和方法,让娱乐成为我们生活中的一抹亮色。一、明确娱乐目的首先,明确娱乐的目的至关重要。是为了放松身心、缓解压力,还是为了增进人际关系、拓宽视野?目......
  • 利士策分享走进自然的怀抱,触碰生命的韵律,领悟生活的真谛
     在这个喧嚣纷扰的世界里,我们时常被各种琐事缠绕,心灵如同久旱的土地渴望甘霖。而大自然,正是那最滋润、最疗愈的源泉。每当我踏入那片未被尘世玷污的绿意之中,便仿佛踏入了一个全新的世界,心灵得到了前所未有的滋养与净化。晨曦初照:新生的希望与启示当第一缕阳光穿透薄雾,轻轻......
  • Taro(ABC 371)
    #include<bits/stdc++.h>#defineendl'\n'#defineintllusingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();signedmain(){#ifdefGordenfreopen("in.txt","rt",stdi......
  • 前端网络请求库:Axios
    目录1.网络请求的基本概念1.1网络请求的基础HTTP协议1.2HTTP工作原理1.3TCP连接1.31建立TCP连接1.31关闭TCP连接1.4HTTP的请求方法1.5HTTP的响应状态码分类1.6.前端网络请求方式2.Axios在在vue项目中的使用 2.1安装与使用2.2Axios使用HTTP请求方法2.2......
  • JupyterLab
    jupyter.org安装PIP:pipinstalljupyterlabmacOS:brewinstalljupyterlab设置密码jupyterlabpassword启动jupyterlab启动SSH本地转发很多时候我们是在服务器上使用Jupyter的,为了能直接在http://127.0.0.1:8888/lab上打开Jupyter,我们可以启动SSH本地......
  • \r,\n,\r\n的区别
    回车和换行来源回车”(CarriageReturn)和“换行”(LineFeed)在计算机还没有出现之前,有一种叫做电传打字机(TeletypeModel33)的玩意儿,每秒钟可以打10个字符。但它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符......
  • 2023年全国高中数学联合竞赛A卷加试P3:组合极值、染色
    题目求具有下述性质的最小正整数$k$:若将$1,2,\cdots,k$中的每个数任意染为红色或者蓝色,则或者存在$9$个不同的红色的数$x_1,x_2,\cdots,x_9$满足$x_1+x_2+\cdots+x_8<x_9,$或者存在$10$个互不相同的蓝色的数$y_1,y_2,\cdots,y_{10}$满足$y_1+y_2+\cdots+y_9<y_{10}.$解......