1. 首先创建定时任务实体
/**
 * @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()取消执行任务;

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐