网站首页> 文章专栏> springboot 中定时任务
springboot 中定时任务
原创 时间:2024-04-01 15:11 作者:AI智能 浏览量:760

我们在编程中,都会使用到定时任务来跑,比如数据库同步呀,或者token获取呀

1、定时任务实现的集中方式

1、常见定时任务 Java自带的java.util.Timer类
timer:配置比较麻烦,时间延后问题
timertask:不推荐

2、Quartz框架
配置更简单

xml或者注解

3、SpringBoot使用注解方式开启定时任务
1)启动类里面 @EnableScheduling开启定时任务,自动扫描
2)定时任务业务类 加注解 @Component被容器扫描

3)定时执行的方法加上注解 @Scheduled(fixedRate=2000) 定期(每2s)执行一次

import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication //一个注解顶下面3个
@EnableScheduling	//开启定时任务
public class FbiaoApplication {

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

@Component
public class TestTask {
	@Scheduled(fixedRate=2000) //两秒执行一次
	public void sum(){
		System.out.println("当前时间:"+new Date());
	}
}

4、SpringBoot常用定时任务表达式配置和在线生成器

案例1:
cron 定时任务表达式 @Scheduled(cron="*/1 * * * * *") 表示每秒
crontab 工具 https://tool.lu/crontab/

各种使用方法spring crontab

   @Scheduled(cron="*/1 * * * * *")//每秒执行一次
    public void testTask(){
        System.out.println("当前时间"+new Date());
    }


    @Scheduled(fixedDelay = 2000) //与 fixedDelayString=“2000”等价(字符串形式)
    public void testTask() throws InterruptedException {
        Thread.sleep(4000L);
        System.out.println("当前时间"+new Date());
    }
@Scheduled(cron="*/10 * * * * *")

@Scheduled(fixedRate = 1000*10)

fixedRate启动时,会运行一次,然后按所设置的间隔时间去执行。可以适用于定时刷新。
cron,启动时,不会去运行一次,而是根据表达式内的固定时间去启动!

两者可根据需要去设置


常用cron表达式

         每隔5秒执行一次:*/5 * * * * ?

每隔1分钟执行一次:0 */1 * * * ? 每天23点执行一次:0 0 23 * * ? 每天凌晨1点执行一次:ga 每月1号凌晨1点执行一次:0 0 1 1 * ? 每月最后一天23点执行一次:0 0 23 L * ? 每周星期天凌晨1点实行一次:0 0 1 ? * L 在26分、29分、33分执行一次:0 26,29,33 * * * ? 每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?


动态定时任务

解决传统固定死时间的替换。
实现需要借助SpringSchedulingConfigurer接口,该方式可以实现动态时间,定时任务。

1,SchedulingConfigurer
要想实现定时任务主要是实现SchedulingConfigurer接口,然后重写configureTasks方法

2,ScheduledTaskRegistrar
在configureTasks方法中,ScheduledTaskRegistrar通过addTriggerTask来添加触发器任务,从而去执行。而addTriggerTask方法有两个参数,一个是要执行得任务,一个是触发器


注意:动态切换时间的话,并不是立即生效,而是在最后一次执行定时时,在修改时间,下一次执行才是修改后的时间


3,基于接口时间调整

@Component
public class CronSchedule implements SchedulingConfigurer {

    private static final SimpleDateFormat detefarmat = new SimpleDateFormat("HH:mm:ss");
    private static final String DEFAULT_CRON = "0/5 * * * * ?";
    private String cron = DEFAULT_CRON;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //1.添加任务内容(Runnable)
                this::startTask,
                //2.设置执行周期(Trigger)
                triggerContext -> {
                    String corn = cron;
                    return new CronTrigger(corn).nextExecutionTime(triggerContext);
                }
        );
    }

    private void startTask() {
        System.out.println("==========执行定时任务===========");
    }


    public void setCron(String cron) {
        System.out.println("cron更变为" + cron);
        this.cron = cron;
    }

}


创建一个controller

@Autowired
CronSchedule cronSchedule;

@RequestMapping(value = "/updateCron")
public String updateCron(@RequestParam("cron") String cron) {
    System.out.println("========  改变定时任务 ==========");
    cronSchedule.setCron(cron);
    return "success";
}

这样既可实现!


4,基于数据库实现动态
注意点:这里配置的会有bug,只能修改定时任务的时间,不能移除定时任务,不能添加定时任务

  • 创建数据库(tb_schedule_task)

  • 1711955448770.webp


  • 配置实体类和mapper层

  • 代码实现
  • @Component
    public class CronSchedule implements SchedulingConfigurer {
        @Autowired
        private TbScheduleTaskMapper tbScheduleTaskMapper;
        private int count = 0;
        
        @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            //第一次启动注入
            List tasks = getAllScheduleTasks();
            System.out.println("====== 定时任务启动了 =========");
            //启动的时候会执行一次,这里我们用count > 0 的时候证明启动了一次可执行定时方法
            if (tasks.size() > 0){
                    for (TbScheduleTask task : tasks) {
                        taskRegistrar.addTriggerTask(getRunnable(task), getTrigger(task));
                    }
                    count++;
            }
        }
    
        /**
         *  定时时间
         * @param tbScheduleTask
         * @return
         */
        private Trigger getTrigger(TbScheduleTask tbScheduleTask) {
            return new Trigger() {
                @Override
                public Date nextExecutionTime(TriggerContext triggerContext) {
                    //这里查询数据库定时任务有被修改吗,修改则替换
                    TbScheduleTask tbScheduleTaskdb = tbScheduleTaskMapper.selectByPrimaryKey(tbScheduleTask.getSeqId());
                    String cron = null;
                    if (tbScheduleTaskdb != null && !tbScheduleTask.getCron().equals(tbScheduleTaskdb.getCron())){
                        cron =  tbScheduleTaskdb.getCron();
                    }else {
                        cron = tbScheduleTask.getCron();
                    }
                    CronTrigger trigger = new CronTrigger(cron);
                    return trigger.nextExecutionTime(triggerContext);
                }
            };
        }
    
        /**
         * 获取Runnable
         * 执行定时任务
         * @param tbScheduleTask
         * @return
         */
        private Runnable getRunnable(TbScheduleTask tbScheduleTask) {
            return new Runnable() {
                @Override
                public void run() {
                    if (count != 0){
                        System.out.println("==========tbScheduleTask=========="+tbScheduleTask.getTaskName());
                    }
                }
            };
        }
        
        /**
         * 获取要执行的所有任务
         * @return
         */
        private List getAllScheduleTasks() {
            TbScheduleTaskExample example = new TbScheduleTaskExample();
            example.createCriteria().andStatusEqualTo(1);
            return tbScheduleTaskMapper.selectByExample(example);
        }
    }

动动小手 !!!
来说两句吧
最新评论
  • 初时模样
    很不错,帮忙解决了,难题!