- 首先创建定时任务实体
/**
* @author liangxuelong
* @version 1.0
* @description: 定时任务配置
* @date 2021/8/25 9:45
*/
@Data
public class Scheduled {
private String id;
private String classPath; //完整类名
private String name; //任务名称
private String cron; //时间表达式
private String description; //描述
private Short status; //0启用 1停用
}
2、 创建定时任务抽象类AbstractJob,定义任务的创建、销毁、执行任务、获取任务名称等方法;
**
* @author liangxuelong
* @version 1.0
* @description: 定时任务抽象类
* @date 2021/8/27 10:36
*/
public abstract class AbstractJob implements Runnable {
public Logger logger = LoggerFactory.getLogger(AbstractJob.class);
private ScheduledFuture<?> scheduledFuture;
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
/**
* 获取任务名称
*/
public abstract String getName();
/**
* 开始执行任务
*/
public abstract void execute();
/**
* @description: 创建定时任务
* @param: cron 时间表达式
* @return: void
* @author liangxuelong
* @date: 2021/8/27
*/
public void createJob(String cron){
try {
scheduledFuture = threadPoolTaskScheduler.schedule(this, new CronTrigger(cron));
} catch (Exception e) {
logger.error("创建定时任务 【"+getName()+"】 失败!");
e.printStackTrace();
}
}
/**
* 定时任务执行之前
*/
public void begin(){
logger.info("------开始执行【"+getName()+"】任务------");
};
/**
* 定时任务执行之后
*/
public void end(){
logger.info("------结束执行【"+getName()+"】任务------");
};
/**
* 取消执行任务
*/
public void cancel(){
try {
if(scheduledFuture!=null)
scheduledFuture.cancel(true);
logger.info("取消执行【"+getName()+"】 任务!");
} catch (Exception e) {
logger.error("取消执行 【"+getName()+"】失败 !");
e.printStackTrace();
}
}
@Override
public void run(){
begin();
execute();
end();
};
}
3、创建定时任务SendMsgJob进行测试
实现抽象类中抽象方法。加@Component交给spring
/**
* @author liangxuelong
* @version 1.0
* @description: 测试定时任务
* @date 2021/8/26 14:04
*/
@Component
public class SendMsgJob extends AbstractJob {
@Override
public void execute() {
logger.info("发送了一条消息");
this.cancel();
}
@Override
public String getName() {
return "定时发送消息";
}
}
4、创建service 层完成添加、删除、修改、查询及立即执行定时任务
这里是
/**
* @author liangxuelong
* @version 1.0
* @description: Scheduled service
* @date 2021/8/16 9:07
*/
@Service
public class ScheduledServiceImpl extends ServiceImpl<ScheduledMapper, Scheduled> implements ScheduledService {
@Autowired
private ApplicationContext context;
@Override
public List<Scheduled> findAllScheduled() {
return list();
}
/**
* @description: 创建定时任务
* @param: scheduled
* @return: void
* @author liangxuelong
* @date: 2021/8/27
*/
@Override
@Transactional
public void createJob(Scheduled scheduled) {
AbstractJob job = null;
try {
job = (AbstractJob) context.getBean(Class.forName(scheduled.getClassPath()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(job!=null){
job.createJob(scheduled.getCron());
}
save(scheduled);
}
/**
* @description: 修改定时任务
* @param: scheduled
* @return: void
* @author liangxuelong
* @date: 2021/8/27
*/
@Override
public void updateJob(Scheduled scheduled) {
AbstractJob job = null;
try {
job = (AbstractJob) context.getBean(Class.forName(scheduled.getClassPath()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(job!=null){
job.cancel(); //先删除
job.createJob(scheduled.getCron());//再创建
}
updateById(scheduled);
}
/**
* @description: 立刻执行定时任务
* @param: scheduled
* @return: void
* @author liangxuelong
* @date: 2021/8/27
*/
@Override
public void executeJob(Scheduled scheduled) {
AbstractJob job = null;
try {
job = (AbstractJob) context.getBean(Class.forName(scheduled.getClassPath()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(job!=null){
job.execute();
}
}
/**
* @description: 删除定时任务
* @param: scheduled
* @return: void
* @author liangxuelong
* @date: 2021/8/27
*/
@Override
public void deleteJob(Scheduled scheduled) {
AbstractJob job = null;
try {
job = (AbstractJob) context.getBean(Class.forName(scheduled.getClassPath()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(job!=null){
job.cancel(); //删除
removeById(scheduled.getId());
}
}
}
5、实现SchedulingConfigurer接口创建定时任务配置类ScheduledConfig;
实现configureTasks方法,用于程序启动完成对数据库里的定时任务进行创建;
/**
* @author liangxuelong
* @version 1.0
* @description: 定时任务配置类
* @date 2021/8/25 9:40
*/
@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {
@Autowired
private ApplicationContext context;
@Autowired
private ScheduledService scheduledService;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//数据库查询到所有的定时任务
List<Scheduled> scheduledList = scheduledService.findAllScheduled();
//创建定时任务
for (Scheduled scheduled : scheduledList) {
AbstractJob task = null;
try {
task = (AbstractJob) context.getBean(Class.forName(scheduled.getClassPath()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
task.createJob(scheduled.getCron());
}
}
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.setPoolSize(20);
executor.setThreadNamePrefix("taskExecutor-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
}
6、数据库添加一条数据进行测试
这里的classPath为包括类名的类完整路径;
时间表达式cron可查看这里配置相应的时间表达式;这里的0/10 * * * * ? 每为10秒执行一次;
7、启动项目测试
可以看见任务在第40秒已成功执行;由于我为了测试移除定时任务所以在SendMsgJob里的execute()方法里调用了cancel();所以执行一次之后定时任务就取消了。本地只是 为了测试方便,可以根据实际情况调用cancel()取消执行任务;