欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于SpringBoot动态定时任务的实现

程序员文章站 2022-05-03 23:49:27
简单介绍通过Spring自己的任务调度包Task实现定时任务的周期动态设置,以及随时启动停止等操作需要注意的是,只能单机使用,集群和分布式结构不要考虑,否则会多次执行。可以考虑任务调度框架Quartz,听说很好用, 我还没用过 - -怎么用首先搞个存储设置信息的表CREATE TABLE `sys_timed_task` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `task_sort` int(11) DEFAULT...

简单介绍

  1. 通过Spring自己的任务调度包Task实现定时任务的周期动态设置,以及随时启动停止等操作
  2. 需要注意的是,只能单机使用,集群和分布式结构不要考虑,否则会多次执行。可以考虑任务调度框架Quartz,听说很好用, 我还没用过 - -

怎么用

  1. 首先搞个存储设置信息的表
CREATE TABLE `sys_timed_task` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `task_sort` int(11) DEFAULT NULL COMMENT '定时任务序号 (两位一组 例:1020)',
  `task_path` varchar(100) DEFAULT NULL COMMENT '定时任务执行类路径',
  `task_cron` varchar(50) DEFAULT NULL COMMENT '执行周期(cron表达式)',
  `is_del` int(2) DEFAULT '10' COMMENT '是否可删除或停用 10|否/20|是 (立刻生效)',
  `creater_name` varchar(50) DEFAULT NULL COMMENT '创建人',
  `create_time` varchar(20) DEFAULT NULL COMMENT '创建时间',
  `enabled` int(2) DEFAULT '10' COMMENT '是否可用 10|可用/20|停用 (立刻生效)',
  `remark` varchar(100) DEFAULT NULL COMMENT '备注-预留',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务配置表';
  1. 定时配置类
package com.runlin.wework.config;

import com.runlin.wework.entity.SysTimedTaskEntity;
import com.runlin.wework.task.dao.SysTimedTaskDao;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.Task;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Description:
 * 动态定时任务配置类
 * <p>
 * ClassName: TimedTaskConfig
 * date: 2020/10/22 13:16
 *
 * @author jo.li
 * @version 1.0
 * @since JDK 1.8
 */
@Configuration
public class TimedTaskConfig implements SchedulingConfigurer {
    @Resource
    private ApplicationContext context;
    @Resource
    private SysTimedTaskDao timedTaskDao;


    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    	// 这里也可以不用selectAll(),自己写个条件查询提前把禁用或已删除数据提出也可以
        for(SysTimedTaskEntity timedTaskEntity : timedTaskDao.selectAll()){
            Class<?> clazz;
            Object task;
            try {
            	// 根据类路径获取实例
                clazz = Class.forName(timedTaskEntity.getTaskPath());
                // 生成bean(放spring里)
                task = context.getBean(clazz);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("sys_timed_task表数据" + timedTaskEntity.getTaskPath() + "有误", e);
            } catch (BeansException e) {
                throw new IllegalArgumentException(timedTaskEntity.getTaskPath() + "不是SpringBean", e);
            }
            Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类没有实现ScheduledOfTask接口");
            // 可以通过改变数据库数据进而实现动态改变执行周期
            taskRegistrar.addTriggerTask(((Runnable) task),
                    triggerContext -> {
                        String cronExpression = timedTaskEntity.getTaskCron();
                        return new CronTrigger(cronExpression).nextExecutionTime(triggerContext);
                    }
            );
        }
    }
	/**
     * 搞个池子给Spring,初始的定时放这里执行 
     * @return: java.util.concurrent.Executor
     * @Author jo.li
     * @Description taskExecutor <br/>
     * @Date 2020/11/11 17:30
     **/
    @Bean
    public Executor taskExecutor() {
    	// 核心线程数根据定时数量和执行效率来
        return new ScheduledThreadPoolExecutor(10, new ThreadFactory() {
            int counter = 0;
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r,"数据统计-Thread-"+counter);
                counter++;
                return thread;
            }
        });
    }
}
  1. 定时实现接口
package com.runlin.wework.config;

import com.runlin.wework.common.GlobalConstant;
import com.runlin.wework.entity.SysTimedTaskEntity;
import com.runlin.wework.task.dao.SysTimedTaskDao;
import com.runlin.wework.utils.SpringUtils;

/**
 * Description:
 * <p>
 * ClassName: ScheduledOfTask
 * date: 2020/10/22 13:23
 *
 * @author jo.li
 * @version 1.0
 * @since JDK 1.8
 */
public interface ScheduledOfTask extends Runnable {
    /**
     * 定时任务业务实现方法
     *
     * @return: void
     * @Author jo.li
     * @Description execute <br/>
     * @Date 2020/10/22 14:43
     **/
    void execute();

    /**
     * 实现控制定时任务启用或禁用的功能
     *
     * @return: void
     * @Author jo.li
     * @Description run <br/>
     * @Date 2020/10/22 14:12
     **/
    @Override
    default void run() {
        SysTimedTaskDao timedTaskDao = SpringUtils.getBean(SysTimedTaskDao.class);
        SysTimedTaskEntity timedTaskEntity = timedTaskDao.getTimedTaskByPath(this.getClass().getName());
        // 禁用或已删除
        if (GlobalConstant.NO_ENABLED.equals(timedTaskEntity.getEnabled()) ||
                GlobalConstant.IS_DEL.equals(timedTaskEntity.getIsDel())) {
            return;
        }
        // 执行
        execute();
    }
}
  1. 定时任务类使用执行类添加注解@Component 实现接口ScheduledOfTask就OK了
package com.runlin.wework.task.data;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Description:
 * 各类问题咨询人数统计
 * <p>
 * ClassName: QuestionPerDayStatistics
 * date: 2020/10/23 14:29
 *
 * @author jo.li
 * @version 1.0
 * @since JDK 1.8
 */
@Component
public class QuestionPerDayStatistics implements ScheduledOfTask {
    @Resource
    private DataStatisticsUtils statisticsUtils;
    private final Logger log = LoggerFactory.getLogger(getClass());
    /**
     * 统计初始值
     */
    private final String INIT_NUM = "1";

    /**
     * 定时任务业务实现方法
     *
     * @return: void
     * @Author jo.li
     * @Description execute <br/>
     * @Date 2020/10/22 14:43
     **/
    @Override
    public void execute() {
        log.info("各类问题咨询人数统计定时开始运行!");
        
        log.info("各类问题咨询人数统计定时运行结束!");
    }
}
  1. 页面启用停用有时间再说。

本文地址:https://blog.csdn.net/qq_38402364/article/details/109626848

上一篇: Spring整合JMS

下一篇: jms