先简单说下两个方式的区别:
注解方式的优点是简单方便,同样的缺点也明显就是执行周期是固定的不能动态修改。
实现接口的方式可以通过将cron表达式保存到数据库中,从数据库中读取从而改变执行时间。
@Scheduled方式实现定时任务
需要注意的是@Scheduled里的cron 只有6个域
package com.demo.schedule;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class StaticTask{
@Scheduled(cron = "0/5 * * * * ?")
public void doTask(){
System.out.println("定时任务每5秒执行: "+LocalDateTime.now());
}
}
SchedulingConfigurer接口方式实现定时任务
这里注意的是通过实现接口重新方法的方式实现定时任务,需要在任务类或者启动类上@EnableScheduling
demo代码是表中有个cron表里面有设置好的cron表达式。通过查询动态设置。
重写的方法其实是这个类去实际实行scheduledTaskRegistrar.addTriggerTask(Runnable task,Trigger trigger)
task:需要执行的任务,本质其实就是一个线程
trigger:执行cron的表达式
CronExpression.isValidExpression(cron) 校验cron表达式的合法性,是quartz中的一个类需要额外添加依赖,这个校验不是必须的。
依赖:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
测试代码:
package com.demo.schedule;
import com.demo.mapper.CronMapper;
import com.demo.pojo.Cron;
import org.quartz.CronExpression;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import java.time.LocalDateTime;
@Configuration
public class TestTask implements SchedulingConfigurer {
private CronMapper cronMapper;
public TestTask(CronMapper cronMapper) {
this.cronMapper = cronMapper;
}
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> {
System.out.println("实现接口方式: " + LocalDateTime.now());
}, triggerContext -> {
Cron c = cronMapper.selectByPrimaryKey(1);
String cron = c.getCron();
if (!CronExpression.isValidExpression(cron)) {
//默认10秒
cron = "0/10 * * * * ? ";
}
return new CronTrigger(cron).nextExecutionTime(triggerContext);
});
}
}