通常,在我们的项目中需要定时给前台发送一些提示性消息或者我们想要的定时信息,这个时候就需要使用定时任务来实现这一功能,实现也很简单,接下来具体来看看吧~
简单定时任务
首先,你需要在你的启动类上加上开启定时任务的注解
然后,就可以开始编写一个简单的自定义定时任务的逻辑
@Component public class ScheduleConfig { @Scheduled(cron = "*/5 * * * * ?") public void printNowTime(){ System.out.println("固定定时任务执行:--->"+ LocalDateTime.now()+",此任务为五秒执行一次"); } }
以上的代码逻辑为每五秒打印出当前的时间,控制台打印结果:
@Scheduled除过cron还有三种方式:fixedRate,fixedDelay,initialDelay
cron:表达式可以定制化执行任务,但是执行的方式是与fixedDelay相近的,也是会按照上一次方法结束时间开始算起。
fixedRate:在每次任务完成后等待一定的时间再进行下一次执行,指定连续执行之间的延迟时间。
initialDelay:initialDelay = 10000 表示在容器启动后,延迟10秒后再执行一次定时器。
fixedDelay:是按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。
因此,需要注意fixedRate与fixedDelay的区别:fixedRate
是基于任务开始执行的时间点来计算下一次任务开始执行的时间,因此任务的执行时间间隔是相对固定的,不受到任务执行时间的影响。如果指定的时间间隔小于任务执行的实际时间,则任务可能会并发执行。而fixedDelay
是基于任务执行完成的时间点来计算下一次任务开始执行的时间,因此任务的执行时间间隔是相对不规则的,受到任务执行时间的影响.
cron表达式
cron表达式是一个字符串,分为6或7个域,每两个域之间用空格分隔,
其语法格式为:"秒域 分域 时域 日域 月域 周域 年域"
取值范围
常例
但是,你会发现以上的方式虽然也能实现定时任务,缺点是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便。为了达到实时生效的效果,那么可以使用接口来完成定时任务,统一将定时器信息存放在数据库中。
基于接口的方式
以下是对应数据表信息
使用mybatis-plus实现cron表的mapper、service接口、serviceimpl实现类
接下来实现自定义定时任务,通过从数据库中获取cron表达式
@Component public class CompleteScheduleConfig implements SchedulingConfigurer { @Autowired private CronDao cronMapper; @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addTriggerTask( ()-> System.out.println("时间到了哦,当前时间为"+ LocalDateTime.now().toLocalTime()), // 设置定时任务执行周期,从数据库中获取 triggerContext -> { String cron=cronMapper.selectById(1).getCronExpression(); if(cron==null){ return null; } // 返回执行周期 return new CronTrigger(cron).nextExecutionTime(triggerContext); } ); }
这里我把需要从数据中查的cron表达式id写死了,读者可以根据自己的项目需求进行修改。