关于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...
简单介绍
- 通过Spring自己的任务调度包Task实现定时任务的周期动态设置,以及随时启动停止等操作
- 需要注意的是,只能单机使用,集群和分布式结构不要考虑,否则会多次执行。可以考虑任务调度框架Quartz,听说很好用, 我还没用过 - -
怎么用
- 首先搞个存储设置信息的表
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='定时任务配置表';
- 定时配置类
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;
}
});
}
}
- 定时实现接口
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();
}
}
- 定时任务类使用执行类添加注解@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("各类问题咨询人数统计定时运行结束!");
}
}
- 页面启用停用有时间再说。
本文地址:https://blog.csdn.net/qq_38402364/article/details/109626848
上一篇: Spring整合JMS
下一篇: jms