Springboot 设置动态定时任务,千万别写死了

在spring boot项目中使用定时任务是很简单的啦,只要使用@EnableScheduling@Scheduled两个注解就可以实现,然后借助cron表达式并且要先定义在配置文件中。

最近有两个新需求,现在这种简单使用@Scheduled已经满足不了需求,一个是batch job是定时任务执行,需要在数据库配置cron表达式,来控制定时任务的执行时间。另一个是有个定时任务在线上是每天跑一次,但是在测试环境每天跑一次太耗时,需要我们修改更短的执行频率,下班前要把定时任务又改成和线上一样,所以要在spring boot实现动态定时任务,不然每改一次要提单重新部署一次,想想就想死…

下面用一个demo来实现下动态定时任务

因为只是个demo,只需要引入简单的依赖即可

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

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

启动类:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

定时任务配置文件,这里我们直接新建一个配置文件,定义两个cron表达式
task-config.ini

printTime.task1.cron=0/10 * * * * ?
printTime.task2.cron=0/15 * * * * ?

定时任务执行类

package com.example.demo.scheduler.dynamic;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@PropertySource("classpath:/task-config.ini")
public class ScheduleTask implements SchedulingConfigurer {

    @Value("${printTime.task1.cron}")
    private String task1cron;

    @Value("${printTime.task2.cron}")
    private String task2cron;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> System.out.println("Task1 Current time: " + LocalDateTime.now()), triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(task1cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });

        taskRegistrar.addTriggerTask(() -> System.out.println("Task2 Current time: " + LocalDateTime.now()), triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(task2cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }

    public void setTask1cron(String task1cron) {
        this.task1cron = task1cron;
    }

    public void setTask2cron(String task2cron) {
        this.task2cron = task2cron;
    }
}

定义一个接口,使得可以通过调用接口来动态修改定定时任务的执行时间

package com.example.demo.controller;

import com.example.demo.scheduler.dynamic.ScheduleTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@RestController
@RequestMapping("/base")
public class BaseController {

    private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
    
    @Resource
    private ScheduleTask scheduleTask;

    @GetMapping("/v1/cron/update")
    public String updateCron(String cron, int task) {
        logger.info("new cron: {}", cron);
        if (task == 1) {
            scheduleTask.setTask1cron(cron);
        }
        if (task == 2) {
            scheduleTask.setTask2cron(cron);
        }
        return "ok";
    }
}

接下来启动程序,可以看到Task1每10秒执行一次,Task2每15秒执行一次。
在这里插入图片描述
现在我们调用接口,把Task1修改为每15秒执行一次,Task2修改为每10秒一次。

curl http://localhost:8090/base/v1/cron/update?cron=0/15 * * * * ?&task=1
curl http://localhost:8090/base/v1/cron/update?cron=0/10 * * * * ?&task=2

可以看到定时任务执行时间发生了改变
在这里插入图片描述
另外,除了cron表达式,@Scheduled还支持另一种触发条件,@Scheduled(fixedDelay = 10000L) 该触发条件可以随意设置循环间隔时间,动态定时任务同样也支持这种触发器。

@Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> System.out.println("Task1 Current time: " + LocalDateTime.now()), triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(task1cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });

        taskRegistrar.addTriggerTask(() -> System.out.println("Task2 Current time: " + LocalDateTime.now()), triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(task2cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });

        // PeriodicTrigger
        taskRegistrar.addTriggerTask(() -> System.out.println("Task3 Current time: " + LocalDateTime.now()), triggerContext -> {
            PeriodicTrigger periodicTrigger = new PeriodicTrigger(10000L);
            return periodicTrigger.nextExecutionTime(triggerContext);
        });
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值