1.1 Quartz介绍

Quartz是OpenSymphony开源组织在Job scheduling领域的一个开源项目,由Java开发,可以用来执行定时任务,类似于java.util.Timer。Quartz是功能强大的开源作业调度库,几乎可以集成到任何Java应用程序中。Quartz包含许多企业级功能,例如对JTA事务和集群的支持。Quartz作为定时任务组件,既可以单独使用,也可以整合Spring使用。
官网:http://www.quartz-scheduler.org/
maven坐标:

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

1.2 核心API

在这里插入图片描述

  • Scheduler:任务调度器,使任务和触发器关联,统一进行任务的调度
  • StdSchedulerFactory:任务调度器工厂,可以创建Scheduler对象
  • JobDetail:任务对象
  • JobBuilder:任务构建器,用于创建JobDetail对象
  • Trigger:触发器对象
  • TriggerBuilder:触发器构建器,用于创建Trigger对象
  • JobExecutionContext:任务执行的上下文对象,通过此对象可以获取当前 执行任务的相关信息,例如JobDetail、Trigger对象都可以获取到
  • JobDataMap:保存任务实例的状态信息
  • RAMJobStore:此类实现了一个利用RAM作为其存储设备的JobStore,访问速度极快,但是数据却易失,如果需要在程序关闭之前保持真正的持久性,则不应使用此JobStore
  • JobStoreTX:通过JDBC将所有数据保存在数据库中

1.3 入门案例

1.3.1 代码实现

第一步:创建maven工程,导入Quartz的maven坐标

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

第二步:创建作业类,需要实现Job接口

package cn.test.jobs;import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
 * 自定义Job
 */
public class HelloJob implements Job {
    /**
     * 执行方法
     * @param jobExecutionContext 任务执行上下文对象
     * @throws JobExecutionException
     */
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        System.out.println("自定义Job开始执行:" + formatter.format(now));
    }
}

第三步:基于Quartz提供的API启动任务调度

package cn.test;import cn.itcast.jobs.HelloJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
​
public class HelloJobMain {
    public static void main(String[] args) {
        try {
            //1:创建调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
​
            //2:创建任务实例
            JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).
                    withIdentity("JobDetail_1").
                    build();
            
            //3:创建触发器Trigger
            Trigger trigger = TriggerBuilder.newTrigger().
                    withIdentity("Trigger_1").
                    withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).
                    build();
​
            //4:触发器和任务关联
            scheduler.scheduleJob(jobDetail,trigger);
​
            //5:启动任务调度器
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

查看控制台执行效果:
在这里插入图片描述
1.3.2 问题思考

  1. 针对前面的入门案例,有三个问题需要思考:
  2. 自定义任务HelloJob是单例的还是每次执行定时任务都创建一个实例呢?
  3. 如何给定时任务传递参数并且在执行任务时可以获取到相应参数呢?

入门案例中触发器设置的是每隔5秒执行一次,是否可以使用cron表达式设置触发时间呢?

1. 解答
针对第一个问题,可以为HelloJob类添加无参构造方法:

public HelloJob(){
    System.out.println("创建HelloJob实例");
}

观察控制台输出:
在这里插入图片描述
可以看到每次执行定时任务都会重新创建一个HelloJob实例。

2.解答
针对第二个问题,Quartz为我们提供了相应方法可以在创建任务时设置参数,并且通过提供的上下文对象(JobExecutionContext)来获取参数。

HelloJobMain做如下修改:

package cn.test;import cn.itcast.jobs.HelloJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
​
public class HelloJobMain {
    public static void main(String[] args) {
        try {
            //1:创建调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
​
            //2:创建任务实例
            JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).
                    withIdentity("JobDetail_1").
                    build();
            
            //设置参数,在定时任务执行时可以动态获取这些参数
            jobDetail.getJobDataMap().put("key1","value1");
            jobDetail.getJobDataMap().put("key2","value2");
            
            //3:创建触发器Trigger
            Trigger trigger = TriggerBuilder.newTrigger().
                    withIdentity("Trigger_1").
                    withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).
                    build();
​
            //4:触发器和任务关联
            scheduler.scheduleJob(jobDetail,trigger);
​
            //5:启动任务调度器
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

HelloJob做如下修改:

package cn.test.jobs;import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
​
/**
 * 自定义Job
 */
public class HelloJob implements Job {
    public HelloJob(){
        System.out.println("创建HelloJob实例");
    }
    
    /**
     * 执行方法
     * @param jobExecutionContext 任务执行上下文对象
     * @throws JobExecutionException
     */
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        System.out.println("自定义Job开始执行:" + formatter.format(now));
        
        //通过上下文对象JobExecutionContext可以获取到任务相关参数
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        Set<Map.Entry<String, Object>> entries = jobDataMap.entrySet();
        entries.forEach((entry) -> {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + " = " + value);
        });
    }
}

查看控制台输出效果:
image-20200715094519854
可以看到通过上下文对象可以获取到相应参数。

通过断点调试可以看到上下文对象中封装了很多信息,这些信息都可以通过上下文对象获取到:
image-20200714161555281
3. 解答
针对第3个问题,Quartz是支持cron表达式来设置触发时间的,HelloJobMain做如下修改:

package cn.test;import cn.itcast.jobs.HelloJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
​
public class HelloJobMain {
    public static void main(String[] args) {
        try {
            //1:创建调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
​
            //2:创建任务实例
            JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).
                    withIdentity("JobDetail_1").
                    build();
            
            //设置参数,在定时任务执行时可以动态获取这些参数
            jobDetail.getJobDataMap().put("key1","value1");
            jobDetail.getJobDataMap().put("key2","value2");
            
            //构建cron表达式
            CronScheduleBuilder cronScheduleBuilder = 
                CronScheduleBuilder.cronSchedule("1,5,11,20,27,35 * * * * ?");
            
            //3:创建触发器Trigger
            Trigger trigger = TriggerBuilder.newTrigger().
                    withIdentity("Trigger_1").
                    withSchedule(cronScheduleBuilder).
                    build();
​
            //4:触发器和任务关联
            scheduler.scheduleJob(jobDetail,trigger);
​
            //5:启动任务调度器
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

观察控制台输出:
image-20200715094259244

2. Quartz动态定时任务

前面的入门案例中我们已经通过Quartz实现了简单的定时任务效果,但是这种方式的任务信息是保存在内存中的,如果服务重启后则任务信息都会丢失。通过上下文对象JobExecutionContext可以看到任务的存储是通过RAMJobStore实现的,如下图:
image-20200715095444749
Quartz提供了另外一种方式,即通过JobStoreTX对象将任务相关信息保存在数据库中,这样就可以避免服务重启后任务信息丢失的问题。同时此种方式还支持动态定时任务,例如动态添加定时任务、暂停定时任务、删除定时任务等操作。

2.1 数据模型

Quartz官方提供了一套数据模型(共11张表)用于保存定时任务相关信息,建表脚本:
image-20200715112503213
可以看到Quartz针对不同的数据库提供了不同的sql脚本文件,本课程使用的是MySQL数据库,执行上面MySQL对应的sql脚本,创建如下11张表:
image-20200715165252467

2.2 环境搭建

第一步:创建maven工程并导入maven坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.test</groupId>
    <artifactId>quartzTest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
        <!-- Spring Cloud 版本信息 -->
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
        <spring-boot.version>2.2.5.RELEASE</spring-boot.version>
        <swagger.version>2.9.2</swagger.version>
        <spring-cloud-alibaba-version>2.2.1.RELEASE</spring-cloud-alibaba-version>
        <druid.version>1.1.23</druid.version>
        <java.version>1.8</java.version>
        <commons.lang.version>2.6</commons.lang.version>
        <commons.io.version>2.5</commons.io.version>
        <lombok.version>1.18.4</lombok.version>
        <commons.io.version>2.5</commons.io.version>
        <http-core.version>4.4.9</http-core.version>
        <httpclient.version>4.5.11</httpclient.version>
        <mybatis-spring-boot-starter.version>2.1.0</mybatis-spring-boot-starter.version>
        <mybatis-plus.version>3.3.0</mybatis-plus.version>
        <quartz.version>2.3.0</quartz.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- Spring Cloud begin-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud end-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>${swagger.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement><dependencies>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>${quartz.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.mchange</groupId>
                    <artifactId>c3p0</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.zaxxer</groupId>
                    <artifactId>HikariCP-java6</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--MyBatisPLus-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis-spring-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

第二步:创建springBoot配置文件application.yml

server:
  port: 8080
​
spring:
  application:
    name: quartz-test
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/quartz?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
      username: root
      password: root

第三步:编写定时任务配置类ScheduleConfig

package com.test.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
​
/**
 * 定时任务配置
 *
 * @author
 */
@Configuration
public class ScheduleConfig {
    //调度器工厂,用于创建调度器对象Scheduler
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);
​
        //quartz参数
        Properties prop = new Properties();
        prop.put("org.quartz.scheduler.instanceName", "WitlinkedScheduler");
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        //线程池配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "20");
        prop.put("org.quartz.threadPool.threadPriority", "5");
        //JobStore配置
        prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        //集群配置
        prop.put("org.quartz.jobStore.isClustered", "true");
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
​
        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
​
        factory.setQuartzProperties(prop);
​
        factory.setSchedulerName("pdScheduler");
        //延时启动
        factory.setStartupDelay(3);
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
        factory.setOverwriteExistingJobs(true);
        //设置自动启动,默认为true
        factory.setAutoStartup(true);return factory;
    }
}

第四步:编写Swagger相关配置类ConfigurationSupport

package com.test.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
​
@Slf4j
@Configuration
@EnableSwagger2
public class ConfigurationSupport extends WebMvcConfigurationSupport {
    @Bean
    public Docket createRestApi() {
        // 文档类型
        return new Docket(DocumentationType.SWAGGER_2)
                // 创建api的基本信息
                .apiInfo(apiInfo())
                // 选择哪些接口去暴露
                .select()
                // 扫描的包
                .apis(RequestHandlerSelectors.basePackage("com.test.controller"))
                .paths(PathSelectors.any())
                .build();
    }
​
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger文档")
                .version("1.0")
                .build();
    }
​
    /**
     * 防止@EnableMvc把默认的静态资源路径覆盖了,手动设置的方式
     *
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 解决静态资源无法访问
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        // 解决swagger无法访问
        registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        // 解决swagger的js文件无法访问
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}

第五步:编写自定义任务类HelloJob

package com.test.jobs;import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
​
/**
 * 自定义Job
 */
public class HelloJob extends QuartzJobBean {
    //任务触发时执行此方法
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String time = dateTimeFormatter.format(now);
​
        Object bizId = context.getJobDetail().getJobDataMap().get("bizId");
        System.out.println("自定义Job...bizId = " + bizId + " 执行时间" + time);
    }
}

第六步:编写启动类QuartzApplication

package com.test;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
@SpringBootApplication
public class QuartzApplication {
    public static void main(String[] args) {
        SpringApplication.run(QuartzApplication.class,args);
    }
}

第七步:编写QuartzController

package com.test.controller;import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
​
@RestController
@RequestMapping("/quartz")
public class QuartzController {
    //注入调度器对象
    @Autowired
    private Scheduler scheduler;
}

2.3 实现定时任务

2.3.1 添加定时任务
在QuartzController中创建save方法

/**
* 添加定时任务
* @param bizId
* @return
*/
@PostMapping
@ApiOperation("添加定时任务")
public String save(String bizId,String cronExpression) throws Exception{
    //构建job信息
    JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity(bizId).build();
    jobDetail.getJobDataMap().put("bizId",bizId);
​
    //表达式调度构建器
    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression)
        .withMisfireHandlingInstructionDoNothing();
​
    //按新的cronExpression表达式构建一个新的trigger
    CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(bizId).withSchedule(scheduleBuilder).build();
​
    //关联任务和触发器
    scheduler.scheduleJob(jobDetail,trigger);
    return "OK";
}

在这里插入图片描述

2.3.2 暂停定时任务
在QuartzController中创建pause方法

/**
* 暂停定时任务
* @param bizId
* @return
*/
@PutMapping("/pause/{bizId}")
@ApiOperation("暂停定时任务")
public String pause(@PathVariable String bizId) throws Exception{
    JobKey jobKey = JobKey.jobKey(bizId);
    scheduler.pauseJob(jobKey);
    return "OK";
}

在这里插入图片描述

2.3.3 恢复定时任务
在QuartzController中创建resume方法

/**
* 恢复定时任务
* @param bizId
* @return
*/
@PutMapping("/resume/{bizId}")
@ApiOperation("恢复定时任务")
public String resume(@PathVariable String bizId) throws Exception{
    JobKey jobKey = JobKey.jobKey(bizId);
    scheduler.resumeJob(jobKey);
    return "OK";
}

在这里插入图片描述

2.3.4 删除定时任务
在QuartzController中创建delete方法

/**
* 删除定时任务
* @param bizId
* @return
*/
@DeleteMapping
@ApiOperation("删除定时任务")
public String delete(String bizId) throws Exception{
    JobKey jobKey = JobKey.jobKey(bizId);
    scheduler.deleteJob(jobKey);
    return "OK";
}

在这里插入图片描述

2.3.5 立即执行定时任务
在QuartzController中创建run方法

/**
* 立即执行定时任务
* @param bizId
* @return
*/
@PutMapping("/run/{bizId}")
@ApiOperation("立即执行定时任务")
public String run(@PathVariable String bizId) throws Exception{
    JobKey jobKey = JobKey.jobKey(bizId);
    scheduler.triggerJob(jobKey);
    return "OK";
}

在这里插入图片描述

2.3.6 更新定时任务
在QuartzController中创建update方法

/**
* 更新定时任务
* @param bizId
* @param cronExpression
* @return
* @throws Exception
*/
@PutMapping
@ApiOperation("更新定时任务")
public String update(String bizId,String cronExpression) throws Exception{
    TriggerKey triggerKey = TriggerKey.triggerKey(bizId);
​
    //表达式调度构建器
    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression)
        .withMisfireHandlingInstructionDoNothing();
​
    //获取触发器对象
    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
​
    //按新的cronExpression表达式重新构建trigger
    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
​
    scheduler.rescheduleJob(triggerKey, trigger);
    return "OK";
}

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐