Java使用quartz定时框架通过秒数动态修改间隔时间

问题描述

我们一般在使用定时框架的时候需要动态的控制定时任务的执行时间间隔, 平常我们都是使用cron表达式来实现, 但是如果我们的得到的参数是具体的秒数或者是分钟亦或者是小时, 如果是整数使用cron还可以, 当然cron是不允许出现60分钟执行一次的, 只能是1小时, 准确来说分钟不能超过59分钟否则会报错, 如果不是整数, 那么使用cron表达式会出现时间精度的丢失, 比如说我要一个半小时执行一次, 我通过时间转换的cron表达式, 可能只会每小时的30钟执行, (也可能是方法不对), 基于以上问题的出现, 网上找到一种办法, 如果参数是时间的话, 小时也好, 几十分钟也罢, 我们可以将其转换为秒数, 让它按照指定间隔的秒数去执行.

代码示例

pom.xml

<dependencies>
	 <!-- 引入quartz依赖 -->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-quartz</artifactId>
         <version>2.3.12.RELEASE</version>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
         <version>2.3.12.RELEASE</version>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
         <version>2.3.12.RELEASE</version>
     </dependency>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.18.22</version>
     </dependency>
 </dependencies>

添加配置类

QuartzConfiguration

import org.quartz.Scheduler;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**
 * quartz配置类
 */
@Configuration
public class QuartzConfiguration extends AdaptableJobFactory implements SchedulerFactoryBeanCustomizer {


    //初始化quartz监听器
    @Bean
    public QuartzInitializerListener quartzInitializerListener(){
        return new QuartzInitializerListener();
    }

    //通过调度器工厂实例化调度器
    @Bean
    public Scheduler scheduler(){
        return schedulerFactoryBean().getScheduler();
    }


    //并行
    @Override
    public void customize(SchedulerFactoryBean schedulerFactoryBean) {
        schedulerFactoryBean.setStartupDelay(2);
        schedulerFactoryBean.setAutoStartup(true);
        schedulerFactoryBean.setOverwriteExistingJobs(true);
    }

    @Autowired
    public JobFactory jobFactory;

    /**
     * 方法名:
     * 功能:定义quartz调度工厂
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(){
        // 修改之后方可解决调用service空指针问题
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setJobFactory(jobFactory);
        //是否覆盖之前的定时任务
        factoryBean.setOverwriteExistingJobs(true);
        // 延时启动(秒)
        factoryBean.setStartupDelay(0);
        System.out.println("scheduler 初始化成功!");
        return factoryBean;
    }


}

JobFactory

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Service;

/***
 * 解决调用 service 空指针
 */
@Service("jobFactory")
public class JobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

添加控制器

import com.gsz.quartz.task.QuartzTask;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Project: hyfxiot
 * explain: 控制定时任务的添加和重置.
 */
@Component
public class ScheduledManage {

    // 调度器对象
    @Autowired
    private Scheduler scheduler;

    /**
     * 添加定时任务
     *
     * @param jName   工作明细
     * @param triggerName   触发器名称
     * @param seconds 执行间隔秒数
     */
    public void addJob(String jName, String triggerName, int seconds) {

        try {
            //构建JobDetail工作明细  //test.testJob
            JobDetail jobDetail = JobBuilder.newJob(QuartzTask.class).withIdentity(jName).build();

            //构建Trigger触发器
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerName)
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(seconds)
                            .repeatForever())
                    .build();

            //启用调度器 来执行工作
            scheduler.start();
            scheduler.scheduleJob(jobDetail, trigger);

        } catch (Exception e) {
            System.out.println("创建定时任务失败了," + e);
        }
    }

    /**
     * 重置任务的cron规则
     * @param triggerName 触发器名称 (需要跟添加时设置的触发器名称一致)
     * @param seconds 定时规则 秒数
     */
    public void rescheduleJob(String triggerName,int seconds) {
        try {
            //创建触发器的名字
//            TriggerKey triggerKey = TriggerKey.triggerKey(tName, tGroup);
            // 只有触发器名 没有分组.
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);

            // 使用 SimpleScheduleBuilder
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerKey)
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(seconds)
                            .repeatForever())
                    .build();

            //按照新的trigger来执行job工作  重启触发器
            scheduler.rescheduleJob(triggerKey, trigger);

        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
    
}

controller

import com.gsz.quartz.config.ScheduledManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;

/**
 * @Author gsz
 * @Project: quartz-demo02
 * @Date 2023/8/14 上午 9:53
 * explain:
 */
@RestController
public class QuartzController {

    // 任务控制器
    @Autowired
    private ScheduledManage scheduledManage;

    /**
     * 设置定时任务
     * @param seconds 间隔时间 /s
     */
    @GetMapping("/setTask/{seconds}")
    public String setTask(@PathVariable("seconds") Integer seconds){
        if (Objects.isNull(seconds) || seconds <= 0) return "seconds不合法!";

        // 添加定时任务
        scheduledManage.addJob("quartzTask","testTrigger",seconds);

        return "设置任务成功!";
    }

    /**
     * 重置定时任务
     * @param seconds 秒数
     */
    @GetMapping("/updateTask/{seconds}")
    public String updateTask(@PathVariable("seconds") Integer seconds){
        if (Objects.isNull(seconds) || seconds <= 0) return "seconds不合法!";

        // 重置任务
        scheduledManage.rescheduleJob("testTrigger",seconds);

        return "任务重置成功!";
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值