SpringBoot基于数据库的定时任务实现
在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现。
基于注解来创建定时任务非常简单,只需几行代码便可完成。实现如下:
- @Configuration
- @EnableScheduling
- public class SimpleScheduleTask {
- //10秒钟执行一次
- @Scheduled(cron = "0/10 * * * * ?")
- private void tasks() {
- System.out.println("【定时任务】 每10秒执行一次!");
- }
- }
Cron表达式参数分别表示(从左到右):
秒(0~59) 如0/5表示每5秒
分(0~59)
时(0~23)
日(0~31) 月的某一天
月(0~11)
周几( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)
就上面几行代码,就能搞定一个定时任务。显然,使用Scheduled 确实特别的方便,但有很大的缺点和局限,就是当我们调整了执行计划的时间时,需要重启服务才能生效,这就有些不方便。为了达到实时生效的效果,可以通过数据库来动态实现定时任务。
基于数据库的动态定时任务实现
将定时任务配置在数据库,启动项目的时候,用mybatis读取数据库,实例化对象,并设定定时任务。如果需要新增,减少,修改定时任务,仅需要修改数据库资料,并重启项目即可,无需改代码。
- @Lazy(value = false)
- @Component
- public class ScheduleTask implements SchedulingConfigurer {
- protected static Logger logger = LoggerFactory.getLogger(ScheduleTask.class);
- private SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- @Autowired
- private ScheduleTaskMapper scheduleTaskMapper;
- @Override
- public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
- List<ScheduleTask> tasks = getAllScheduleTasks();
- logger.info("【定时任务启动】 启动任务数:"+tasks.size()+"; time="+sdf.format(new Date()));
- //校验数据
- checkDataList(tasks);
- //通过校验的数据执行定时任务
- int count = 0;
- if(tasks.size()>0) {
- for (int i = 0; i < tasks.size(); i++) {
- try {
- taskRegistrar.addTriggerTask(getRunnable(tasks.get(i)), getTrigger(tasks.get(i)));
- count++;
- } catch (Exception e) {
- logger.error("task start error:" + tasks.get(i).getClassName() + ";" + tasks.get(i).getMethodName() + ";" + e.getMessage());
- }
- }
- }
- logger.info("started task number="+count+"; time="+sdf.format(new Date()));
- };
- /**
- * 获取要执行的所有任务
- * @return
- */
- private List<ScheduleTask> getAllScheduleTasks() {
- ScheduleTaskExample example=new ScheduleTaskExample();
- example.createCriteria().andIsDeleteEqualTo((byte) 0);
- return scheduleTaskMapper.selectByExample(example);
- }
- /**
- * 获取Runnable
- *
- * @param task
- * @return
- */
- private Runnable getRunnable(ScheduleTask task){
- return new Runnable() {
- @Override
- public void run() {
- try {
- Object obj = SpringUtil.getBean(task.getClassName());
- Method method = obj.getClass().getMethod(task.getMethodName(),null);
- method.invoke(obj);
- } catch (InvocationTargetException e) {
- logger.error("refect exception:"+task.getClassName()+";"+task.getMethodName()+";"+ e.getMessage());
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
- };
- }
- /**
- * 获取Trigger
- *
- * @param task
- * @return
- */
- private Trigger getTrigger(ScheduleTask task){
- return new Trigger() {
- @Override
- public Date nextExecutionTime(TriggerContext triggerContext) {
- //将Cron 0/1 * * * * ?
- CronTrigger trigger = new CronTrigger(task.getCron());
- Date nextExec = trigger.nextExecutionTime(triggerContext);
- return nextExec;
- }
- };
- }
- /**
- * 校验数据
- *
- * @param list
- * @return
- */
- private List<ScheduleTask> checkDataList(List<ScheduleTask> list) {
- String msg="";
- for(int i=0;i<list.size();i++){
- if(!checkOneData(list.get(i)).equalsIgnoreCase("ok")){
- msg+=list.get(i).getTaskName()+";";
- list.remove(list.get(i));
- i--;
- };
- }
- if(!StringUtils.IsEmpty(msg)){
- msg="未启动的任务:"+msg;
- logger.error(msg);
- }
- return list;
- }
- /**
- * 按每一条校验数据
- *
- * @param task
- * @return
- */
- private String checkOneData(ScheduleTask task){
- String result="ok";
- Class cal= null;
- try {
- cal = Class.forName(task.getClassName());
- Object obj =SpringUtil.getBean(cal);
- Method method = obj.getClass().getMethod(task.getMethodName(),null);
- String cron=task.getCron();
- if(StringUtils.isBlank(cron)){
- result="no found the cron:"+task.getTaskName();
- logger.error(result);
- }
- } catch (ClassNotFoundException e) {
- result="not found the class:"+task.getClassName()+ e.getMessage();
- logger.error(result);
- } catch (NoSuchMethodException e) {
- result="not found the method:"+task.getClassName()+";"+task.getMethodName()+";"+ e.getMessage();
- logger.error(result);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- return result;
- }
- }
数据库配置
运行的结果
这样我们可以通过直接修改数据库,执行周期就会改变,并且不需要我们重启应用,十分方便。
推荐阅读:
扫码关注公众号,发送关键词获取相关资料:
发“Springboot”领取电商项目实战源码;
发“SpringCloud”领取学习实战资料;
SpringBoot基于数据库的定时任务实现的更多相关文章
- SpringBoot基于数据库的定时任务统一管理
定时任务1 import lombok.extern.slf4j.Slf4j; /** * @author Created by niugang on 2019/12/24/15:29 */ @Slf ...
- SpringBoot基于数据库实现简单的分布式锁
本文介绍SpringBoot基于数据库实现简单的分布式锁. 1.简介 分布式锁的方式有很多种,通常方案有: 基于mysql数据库 基于redis 基于ZooKeeper 网上的实现方式有很多,本文主要 ...
- springboot 基于@Scheduled注解 实现定时任务
前言 使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式: 一.基于注解(@Scheduled) 二.基于接口(SchedulingConfigurer) 前者相信大家都很熟悉, ...
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例
1.前言 本文主要介绍使用SpringBoot与shiro实现基于数据库的细粒度动态权限管理系统实例. 使用技术:SpringBoot.mybatis.shiro.thymeleaf.pagehelp ...
- 四、springBoot 优雅的创建定时任务
前言 好几天没写了,工作有点忙,最近工作刚好做一个定时任务统计的,所以就将springboot 如何创建定时任务整理了一下. 总的来说,springboot创建定时任务是非常简单的,不用像spring ...
- SpringBoot2.0整合mybatis、shiro、redis实现基于数据库权限管理系统
转自https://blog.csdn.net/poorcoder_/article/details/71374002 本文主要介绍使用SpringBoot与shiro实现基于数据库的细粒度动态权限管 ...
- SpringBoot基于websocket的网页聊天
一.入门简介正常聊天程序需要使用消息组件ActiveMQ或者Kafka等,这里是一个Websocket入门程序. 有人有疑问这个技术有什么作用,为什么要有它?其实我们虽然有http协议,但是它有一个缺 ...
- 基于数据库、redis和zookeeper实现的分布式锁
基于数据库 基于数据库(MySQL)的方案,一般分为3类:基于表记录.乐观锁和悲观锁 基于表记录 用表主键或表字段加唯一性索引便可实现,如下: CREATE TABLE `database_lock` ...
- 为什么要用hibernate 与基于数据库表结构的项目开发
最近开始学习hibernate,其实并不知道要学习什么,有什么用.后来问了一下同事,他就说快捷方便简单,很多事情不用自己做他会帮你做好,但是我觉得不应该是这样的,于是我就去搜了一下,就搜到了一篇帖子, ...
随机推荐
- 小白学 Python 爬虫(24):2019 豆瓣电影排行
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 进程间通讯IPC的几种方式总结
Linux进程间的通讯 Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同.前者对Unix早期的进程间通信 ...
- 第四十一篇 入门机器学习——Numpy的基本操作——聚合操作
No.1. 对向量元素求和使用np.sum,也可以使用类似big_array.sum()的方式 No.2. 对向量元素求最小值使用np.min,求最大值使用np.max,也可以使用类似big_arra ...
- linux下grep分析apache日志的命令集合
https://my.oschina.net/hmc0316/blog/112004 实例:月份英文简写英文全称一月Jan.January二月Feb.February三月Mar.March四月Apr. ...
- 基于SILVACO ATLAS的a-IGZO薄膜晶体管二维器件仿真(01)
最近因为肺炎的缘故,宅在家里不能出门,就翻了下一些资料,刚好研究方向是这个,就简单研究了下.参考资料主要如下: 1.<半导体工艺和器件仿真软件Silvaco TCAD实用教程> 唐龙谷 2 ...
- Jarvis OJ - 爬楼梯 -Writeup
Jarvis OJ - 爬楼梯 -Writeup 本来是想逆一下算法的,后来在学长的指导下发现可以直接修改关键函数,这个题做完有种四两拨千斤的感觉,记录在这里 转载请标明出处:http://www.c ...
- (转载)Docker的boot2docker.iso镜像使用
原文路径:https://blog.csdn.net/jiangjingxuan/article/details/54908272#commentsedit 在Docker首次启动时需要下载的一个bo ...
- 265. 粉刷房子 II
Q: A: 首先这题可以和粉刷房子这题一样解法,对于i号房子,遍历k种颜色,对于每一种,都去找i-1号房子除该颜色之外的最小花费.但上一题是3种颜色,总复杂度O(N),这题k种颜色,复杂度O(NK^2 ...
- java的动态绑定和多态
public class Shape { public void area() { System.out.println("各种形状的面积..."); } public stati ...
- 【资源分享】Gmod-Expression2 - 自定义像素画生成
*作者:BUI* 可自定义制作属于你的像素画(默认为Sans) 第77行的COLOR可编辑你想要的颜色(RGB值) 1,2,3,4分别代表第77行所定义的颜色(0代表不显示) 视频地址:传送链接 @n ...