定时任务:Quartz

Quartz简介

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。

quartz是开源且具有丰富特性的"任务调度库",能够集成于任何的java应用,小到独立的应用,大至电子商业系统。quartz能够创建亦简单亦复杂的调度,以执行上十、上百,甚至上万的任务。任务job被定义为标准的java组件,能够执行任何你想要实现的功能。quartz调度框架包含许多企业级的特性,如JTA事务、集群的支持。

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

官网:http://www.quartz-scheduler.org/


Quartz体系结构

jobdetail和trigger的关系是1对n


Quartz常用API

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

  • Scheduler:用于与调度程序交互的主程序接口。通过Scheduler来绑定jobdetail和trigger。只有安排进执行计划的任务Job(通过scheduler.scheduleJob方法安排进执行计划),当它预先定义的执行时间到了的时候(任务触发trigger),该任务才会执行。
  • Job:预先定义的任务逻辑。
  • JobDetail:定时任务的实例,JobDetail实例是通过JobBuilder类创建的,Scheduler真正调度的是JobDetail而不是job。
  • JobDataMap:可以包含不限量的(序列化的)数据对象,可以看作JobDetail内业务逻辑运行时的需要的一系列参数。
  • Trigger :触发器,Trigger对象是用来触发执行Job的。当调度一个job时,我们实例一个触发器然后调整它的属性来满足job执行的条件。表明任务在什么时候会执行。定义了一个已经被安排的任务将会在什么时候执行的时间条件,比如每2秒就执行一次。
  • JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如任务名、组名等,这个声明的实例将会作为一个实际执行的任务。
  • TriggerBuilder :用于声明触发器trigger实例。
  • JobListener、TriggerListener、SchedulerListener:监听器,用于对组件的监听。
  • ......

两个重要注解

@DisallowConcurrentExecution

作用:禁止同一任务定义的多个实例并发执行,确保任务在前一次执行完成后才会触发下一次执行。

解释:一个定时任务5秒钟触发一次,执行一次需要10分钟。打上这个注解后,在打上这个注解后,在上一个任务执行结束前,即使已经到了它的执行时间,也要等待上一个任务执行结束。

@PersistJobDataAfterExecution

作用:在执行完成后持久化JobDataMap中的数据,使任务状态可以在多次执行间保持。

解释:在任务中修改JobDataMap中的数据,此番修改是永久有效的。


案例

入门案例

新建一个springboot项目,导入quartz依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

写一个HelloJob任务类实现Job接口,重写execute方法

public class HelloJob implements Job {
    @Override
    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);
    }
}

声明JobDetail指定HelloJob,声明Trigger,绑定它俩交给Scheduler调度

public class HelloSchedulerDemo {
    public static void main(String[] args) throws Exception {
        // 1:从工厂中获取任务调度的实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
        JobDetail job = JobBuilder.newJob(HelloJob.class)
        .withIdentity("job1", "group1") // 定义该实例唯一标识
        .build();

        // 3:定义触发器 ,马上执行, 然后每5秒重复执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1") // 定义该实例唯一标识
        .startNow()  // 马上执行
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                      .repeatSecondlyForever(5)) // 简单间隔触发,每5秒执行一次
        .build();

        // 4:使用触发器调度任务的执行
        scheduler.scheduleJob(job, trigger);

        // 5:开启
        scheduler.start();

        // 关闭
        // scheduler.shutdown();

    }
}

使用JobDataMap

当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法。Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。当然,JobDataMap也在JobExecutionContext里面。

JobDataMap里面的值的获取方式

(1)使用Map获取。

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

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

@PersistJobDataAfterExecution
public class HelloJob implements Job {
    private String name;
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Hello, " + name + "!");
        setName("I have changed my name");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class HelloJob implements Job {
    @Override
    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);


        System.out.println("name from job detail:"+jobExecutionContext.getJobDetail().getJobDataMap().get("name"));
        System.out.println("name from trigger:" + jobExecutionContext.getTrigger().getJobDataMap().get("name"));

        System.out.println("name from merge:" + jobExecutionContext.getMergedJobDataMap().get("name"));

        System.out.println("age:"+jobExecutionContext.getJobDetail().getJobDataMap().get("age"));
    }
}
public class HelloSchedulerDemo {
    public static void main(String[] args) throws Exception {
        // 1:从工厂中获取任务调度的实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
        JobDetail job = JobBuilder.newJob(HelloJob.class)
        .withIdentity("job1", "group1") // 定义该实例唯一标识
        .usingJobData("name","cjj")
        .usingJobData("age",18)
        .build();

        // 3:定义触发器 ,马上执行, 然后每5秒重复执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1") // 定义该实例唯一标识
        .startNow()  // 马上执行
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                      .repeatSecondlyForever(5)) // 简单间隔触发,每5秒执行一次
        .usingJobData("name","hlyy")
        .build();

        // 4:使用触发器调度任务的执行
        scheduler.scheduleJob(job, trigger);

        // 5:开启
        scheduler.start();
        // 关闭
        // scheduler.shutdown();

    }
}

输出如下

进行数据库备份操作。当前任务执行的时间:2025-04-25 14:46:39
name from job detail:cjj
name from trigger:hlyy
name from merge:hlyy
age:18

这里注意:如果遇到同名的key,Trigger的优先级更高


有状态的Job

@PersistJobDataAfterExecution
public class HelloJob implements Job {
    private int count;

    @Override
    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 + " 执行第 " + (++count) + " 次");

        // 保存到JobDataMap中
        jobExecutionContext.getJobDetail().getJobDataMap().put("count", count);
    }

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

注意加上@PersistJobDataAfterExecution注解,才会每次保存count的状态,否则每次该JobDetail被调度时,都会将count初始化为0

public class HelloSchedulerDemo {
    public static void main(String[] args) throws Exception {
        // 1:从工厂中获取任务调度的实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
        JobDetail job = JobBuilder.newJob(HelloJob.class)
        .withIdentity("job1", "group1") // 定义该实例唯一标识
        .usingJobData("count",0)
        .build();

        // 3:定义触发器 ,马上执行, 然后每5秒重复执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1") // 定义该实例唯一标识
        .startNow()  // 马上执行
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                      .repeatSecondlyForever(5)) // 简单间隔触发,每5秒执行一次
        .build();

        // 4:使用触发器调度任务的执行
        scheduler.scheduleJob(job, trigger);

        // 5:开启
        scheduler.start();
        // 关闭
        // scheduler.shutdown();

    }
}
4:54:32.523 [DefaultQuartzScheduler_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
进行数据库备份操作。当前任务执行的时间:2025-04-25 14:54:32 执行第 1 次
14:54:37.524 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'group1.job1', class=org.daolong.job.HelloJob
14:54:37.525 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
14:54:37.525 [DefaultQuartzScheduler_Worker-2] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
进行数据库备份操作。当前任务执行的时间:2025-04-25 14:54:37 执行第 2 次
14:54:42.517 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'group1.job1', class=org.daolong.job.HelloJob
14:54:42.518 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
14:54:42.518 [DefaultQuartzScheduler_Worker-3] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
进行数据库备份操作。当前任务执行的时间:2025-04-25 14:54:42 执行第 3 次

Cron触发器

public class HelloSchedulerDemoCronTrigger {

    public static void main(String[] args) throws Exception {
        // 1:从工厂中获取任务调度的实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
        JobDetail job = JobBuilder.newJob(HelloJob.class)
        .withIdentity("job1", "group1") // 定义该实例唯一标识
        .build();

        // 3:定义触发器 ,马上执行, 然后每5秒重复执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1") // 定义该实例唯一标识
        .withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?")) // 每5秒执行一次
        .build();

        // 4:使用触发器调度任务的执行
        scheduler.scheduleJob(job, trigger);

        // 5:开启
        scheduler.start();
        // 关闭
        // scheduler.shutdown();
    }
}

监听器(以SchedulerListener为例)

自定义一个MySchedulerListener实现SchedulerListener接口

public class MySchedulerListener implements SchedulerListener {
    @Override
    public void jobScheduled(Trigger trigger) {
        String jobName = trigger.getJobKey().getName();
        System.out.println(jobName + " 完成部署");
    }

    @Override
    public void jobUnscheduled(TriggerKey triggerKey) {
        System.out.println(triggerKey + " 完成卸载");
    }

    @Override
    public void triggerFinalized(Trigger trigger) {
        System.out.println("触发器被移除 " + trigger.getJobKey().getName());
    }

    @Override
    public void triggerPaused(TriggerKey triggerKey) {
        System.out.println(triggerKey + " 正在被暂停");
    }

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

    @Override
    public void triggerResumed(TriggerKey triggerKey) {
        System.out.println(triggerKey + " 正在从暂停中恢复");
    }

    @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) {
        System.out.println("产生严重错误时调用:   "+msg+"  "+cause.getUnderlyingException());
    }

    @Override
    public void schedulerInStandbyMode() {
        System.out.println("调度器在挂起模式下调用");
    }

    @Override
    public void schedulerStarted() {
        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() {
        System.out.println("调度器的数据被清除时调用");
    }
}
public class HelloSchedulerDemoSchedulerListener {
    public static void main(String[] args) throws Exception {
        // 1:从工厂中获取任务调度的实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
        JobDetail job = JobBuilder.newJob(HelloJob.class)
        .withIdentity("job1", "group1") // 定义该实例唯一标识
        .build();
        // 3:定义触发器 ,马上执行, 然后每5秒重复执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1") // 定义该实例唯一标识
        .startNow()  // 马上执行
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                      .repeatSecondlyForever(5)) // 每5秒执行一次
        .build();

        // 4:使用触发器调度任务的执行
        scheduler.scheduleJob(job, trigger);

        // 创建SchedulerListener
        scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());

        // 移除对应的SchedulerListener
        // scheduler.getListenerManager().removeSchedulerListener(new MySchedulerListener());

        // 5:开启
        scheduler.start();
        // 延迟7秒后关闭
        Thread.sleep(7000);
        // 关闭
        scheduler.shutdown();
    }
}


SpringBoot整合Quartz,实现一个Quartz任务调度中心

参考文章:Spring Boot整合Quartz实现动态配置

完整代码

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>

  <!-- 兼容 Spring Boot 2.6.x 的版本 -->
  <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
  </dependency>
  <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
  </dependency>

  <!--        美化ui-->
  <dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
  </dependency>

  <!--        校验框架-->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>

</dependencies>
# MySQL 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/quartz_db?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Quartz 持久化配置
spring.quartz.job-store-type=jdbc
# 启动时不初始化数据库,我们自己手动初始化过了
spring.quartz.jdbc.initialize-schema=embedded

# Quartz 集群配置
#spring.quartz.properties.org.quartz.jobStore.isClustered: true
#spring.quartz.properties.org.quartz.jobStore.tablePrefix: QRTZ_
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate

在maven的依赖包下找到Quartz 调度器所需的表结构的 SQL 脚本文件,到数据库中手动执行。

E:\apache-maven-3.8.6\repository\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar!\org\quartz\impl\jdbcjobstore\tables_mysql_innodb.sql



@Configuration
public class QuartzConfig {
    @Bean
    public Scheduler myScheduler(SchedulerFactoryBean schedulerFactoryBean) throws Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        scheduler.start();
        scheduler.getListenerManager().addJobListener(new MyJobListener());
        return scheduler;
    }
}

@Component
public class QuartzTestJob extends QuartzJobBean {
    @Override
    protected void executeInternal(org.quartz.JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Quartz Test Job");
    }
}

public interface QuartzService {
    /**
     * 添加定时任务
     */
    void addJob(QuartzCreateParam param) throws SchedulerException;

    /**
     * 修改定时任务
     */
    void updateJob(QuartzUpdateParam param) throws SchedulerException;

    /**
     * 暂停定时任务
     */
    void pauseJob(QuartzDetailParam param) throws SchedulerException;

    /**
     * 恢复定时任务
     */
    void resumeJob(QuartzDetailParam param) throws SchedulerException;

    /**
     * 删除定时任务
     */
    void deleteJob(QuartzDetailParam param) throws SchedulerException;

    /**
     * 定时任务列表
     * @return
     */
    List<QuartzJobDetailDto> jobList() throws SchedulerException;

    /**
     * 定时任务详情
     */
    QuartzJobDetailDto jobDetail(QuartzDetailParam param) throws SchedulerException;
}

@Service
public class QuartzServiceImpl implements QuartzService {
    @Resource(name = "myScheduler")
    private Scheduler scheduler;

    @Override
    public void addJob(QuartzCreateParam param) throws SchedulerException {
        String clazzName = param.getJobClazz();
        String jobName = param.getJobName();
        String jobGroup = param.getJobGroup();
        String triggerName = param.getTriggerName();
        String triggerGroup = param.getTriggerGroup();
        String cron = param.getCron();
        String description = param.getDescription();

        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);


        if (checkExist(jobKey)) {
            throw new BaseException("要添加的任务已经存在:" + jobKey);
        }

        Class<? extends Job> jobClass = null;
        try {
            jobClass = (Class<? extends Job>) Class.forName(clazzName);
        } catch (ClassNotFoundException e) {
            throw new BaseException("找不到任务类:" + clazzName);
        }
        JobDataMap jobDataMap = new JobDataMap();
        if (param.getJobDataMap() != null) {
            jobDataMap.putAll(param.getJobDataMap());
        }


        JobDetail jobDetail = JobBuilder.newJob(jobClass)
        .withIdentity(jobName, jobGroup)
        .usingJobData(jobDataMap)
        .build();

        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

        Trigger trigger = TriggerBuilder.newTrigger()
        .withSchedule(scheduleBuilder)
        .withIdentity(TriggerKey.triggerKey(triggerGroup, triggerName))
        .withDescription(description)
        .build();
        scheduler.scheduleJob(jobDetail, trigger);

        if (!scheduler.isShutdown()) {
            scheduler.start();
        }

    }

    /**
     * 可能出现的情况
     * 1.修改该任务现指定的触发器的cron表达式 (给出triggerName、triggerGroup、cron)
     * 2.为该任务绑定一个新的(新增)触发器 (给出triggerName、triggerGroup、cron)
     * 3.为该任务绑定一个已有触发器 (给出triggerName、triggerGroup)
     */
    @Override
    public void updateJob(QuartzUpdateParam param) throws SchedulerException {
        String jobName = param.getJobName();
        String jobGroup = param.getJobGroup();
        String triggerName = param.getTriggerName();
        String triggerGroup = param.getTriggerGroup();
        String cron = param.getCron();


        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
        TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);


        if (!checkExist(jobKey)) {
            throw new BaseException("要修改的任务不存在:" + jobKey);
        }


        // 情况3
        if (cron.isEmpty()) {
            if (!checkExist(triggerKey)) {
                throw new BaseException("要绑定的任务触发器不存在:" + triggerKey);
            }
            scheduler.scheduleJob(scheduler.getTrigger(triggerKey));
            return;
        }

        // 情况1
        if (checkExist(triggerKey)) {
            // 获取原触发器的状态
            Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);

            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withSchedule(scheduleBuilder)
                    .withIdentity(triggerKey).build();

            /** 更新触发器
             * 停止旧触发器的调度计划。
             * 将新触发器绑定到原任务(JobDetail)。
             * 根据新触发器的配置(如 Cron 表达式、开始/结束时间)生成下一次触发时间。
             * 根据原触发器的状态选择是否继续调度。
             */
            scheduler.rescheduleJob(triggerKey, trigger);

            if (triggerState == Trigger.TriggerState.PAUSED) {
                scheduler.pauseTrigger(triggerKey);
            }
            return;
        }

        // 情况2
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
        Trigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(scheduleBuilder)
                .withIdentity(triggerKey).build();
        scheduler.scheduleJob(trigger);
    }

    @Override
    public void pauseJob(QuartzDetailParam param) throws SchedulerException {
        String jobName = param.getJobName();
        String jobGroup = param.getJobGroup();

        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
        if (checkExist(jobKey)) {
            scheduler.pauseJob(jobKey);
        } else {
            throw new BaseException("要暂停的任务不存在:" + jobKey);
        }

    }

    @Override
    public void resumeJob(QuartzDetailParam param) throws SchedulerException {
        String jobName = param.getJobName();
        String jobGroup = param.getJobGroup();

        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);

        if (checkExist(jobKey)) {
            if (!scheduler.isShutdown()) {
                scheduler.resumeJob(jobKey);
                return;
            }
        }
        throw new BaseException("要恢复的任务不存在:" + jobKey);
    }

    @Override
    public void deleteJob(QuartzDetailParam param) throws SchedulerException {
        String jobName = param.getJobName();
        String jobGroup = param.getJobGroup();

        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);

        if (!checkExist(jobKey)) {
            throw new BaseException("要删除的任务不存在:" + jobKey);
        }

        // 先暂停再删除
        scheduler.pauseJob(jobKey);
        scheduler.deleteJob(jobKey);
    }

    @Override
    public List<QuartzJobDetailDto> jobList() throws SchedulerException {
        // 获取匹配所有任务的matcher
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();

        List<QuartzJobDetailDto> jobDtoList = new ArrayList<>();
        Set<JobKey> jobKeySet = scheduler.getJobKeys(matcher);

        for (JobKey jobKey : jobKeySet) {
            QuartzJobDetailDto jobDto = getJobDtoByJobKey(jobKey);
            jobDtoList.add(jobDto);
        }
        return jobDtoList;
    }

    @Override
    public QuartzJobDetailDto jobDetail(QuartzDetailParam param) throws SchedulerException {
        String jobName = param.getJobName();
        String jobGroup = param.getJobGroup();
        JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
        return getJobDtoByJobKey(jobKey);
    }

    // 检查任务是否存在, 如果存在返回true
    private Boolean checkExist(JobKey jobKey) throws SchedulerException {
        return scheduler.checkExists(jobKey);
    }

    // 检查触发器是否存在, 如果存在返回true
    private Boolean checkExist(TriggerKey triggerKey) throws SchedulerException {
        return scheduler.checkExists(triggerKey);
    }

    // 根据jobKey获取任务详情
    public QuartzJobDetailDto getJobDtoByJobKey(JobKey jobKey) throws SchedulerException {
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        List<Trigger> triggerList = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);

        QuartzJobDetailDto jobDto = new QuartzJobDetailDto();
        jobDto.setJobClazz(jobDetail.getJobClass().toString());
        jobDto.setJobName(jobKey.getName());
        jobDto.setJobGroup(jobKey.getGroup());
        jobDto.setJobDataMap(jobDetail.getJobDataMap());

        List<QuartzTriggerDetailDto> triggerDtoList = new ArrayList<>();
        for (Trigger trigger : triggerList) {
            QuartzTriggerDetailDto triggerDto = new QuartzTriggerDetailDto();
            triggerDto.setTriggerName(trigger.getKey().getName());
            triggerDto.setTriggerGroup(trigger.getKey().getGroup());
            triggerDto.setDescription(trigger.getDescription());

            if (trigger instanceof CronTriggerImpl) {
                CronTriggerImpl cronTriggerImpl = (CronTriggerImpl) trigger;
                String cronExpression = cronTriggerImpl.getCronExpression();
                triggerDto.setCron(cronExpression);

                // 计算最近10次的触发时间
                List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 10);
                triggerDto.setRecentFireTimeList(dates);
            }

            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
            triggerDto.setTriggerState(triggerState.toString());

            triggerDtoList.add(triggerDto);
        }
        jobDto.setTriggerDetailDtoList(triggerDtoList);
        return jobDto;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值