Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【springboot】2.3.7集成定时任务SchedulingConfigurer实例

【springboot】2.3.7集成定时任务SchedulingConfigurer实例

作者头像
用户5640963
发布于 2021-05-27 03:14:32
发布于 2021-05-27 03:14:32
1.1K00
代码可运行
举报
文章被收录于专栏:卯金刀GG卯金刀GG
运行总次数:0
代码可运行

背景:

项目需要启动一个定时执行的任务,该任务的执行可以随时停止执行,要求在数据库配置执行规律。

调研:使用scheduling定时任务与springboot集成;

实例:

第一步:创建一个数据表,保存执行的任务

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*DDL 信息*/------------

CREATE TABLE `hk_sys_task` (
  `id` bigint(21) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `task_uuid` varchar(50) DEFAULT NULL COMMENT '任务UUID',
  `task_name` varchar(50) DEFAULT NULL COMMENT '任务名称',
  `task_cron` varchar(50) DEFAULT NULL COMMENT '任务定时表达式',
  `class_name` varchar(100) DEFAULT NULL COMMENT '任务类',
  `method_name` varchar(100) DEFAULT NULL COMMENT '任务方法',
  `task_type` int(1) DEFAULT NULL COMMENT '任务类型',
  `remark` varchar(250) DEFAULT NULL,
  `del_mark` int(1) DEFAULT '1',
  `flag` int(1) DEFAULT '1',
  `create_user` varchar(50) DEFAULT NULL,
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `modify_user` varchar(50) DEFAULT NULL,
  `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

2、创建springboot的SpringUtil用户获取bean

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2021/5/14 11:19
 **/
@Component
@Slf4j
public class SpringUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
        log.info("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext={},",SpringUtil.applicationContext+"========");
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }
}

3、配置执行任务的类SysTaskConfig

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2021/5/14 9:34
 **/
@Lazy(value = false)
@Component
@Slf4j
public class SysTaskConfig implements SchedulingConfigurer {
    @Resource
    private HkSysTaskMapper hkSysTaskMapper;

    private static ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();

    private static Map<String,ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();

    //从数据库里取得所有要执行的定时任务
    private List<HkSysTask> getAllTasks() {
        LambdaQueryWrapper<HkSysTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HkSysTask::getDelMark,1)
                .eq(HkSysTask::getFlag,1);

        return hkSysTaskMapper.selectList(wrapper);
    }
    static {
        threadPoolTaskScheduler.initialize();
    }
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        List<HkSysTask> allTasks = getAllTasks();
        log.info("定时任务启动,预计启动任务数量={},; time={}",allTasks.size(),LocalDateTime.now());

        //校验数据(这个步骤主要是为了打印日志,可以省略)
        checkDataList(allTasks);

        //通过校验的数据执行定时任务
        int count = 0;
        if(allTasks.size()>0) {
            for (int i = 0; i < allTasks.size(); i++) {
                try {
                    scheduledTaskRegistrar.addTriggerTask(getRunnable(allTasks.get(i)), getTrigger(allTasks.get(i)));
                    count++;
                } catch (Exception e) {
                    log.error("定时任务启动错误:" + allTasks.get(i).getClassName() + ";" + allTasks.get(i).getMethodName() + ";" + e.getMessage());
                }
            }
        }
        log.info("定时任务实际启动数量="+count+"; time="+LocalDateTime.now());
    }
    private static Trigger getTrigger(HkSysTask task){
        return new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                //将Cron 0/1 * * * * ? 输入取得下一次执行的时间
                CronTrigger trigger = new CronTrigger(task.getTaskCron());
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        };

    }
    private static Runnable getRunnable(HkSysTask task){
        return new Runnable() {
            @Override
            public void run() {
                Class<?> clazz;
                try {
                    clazz = Class.forName(task.getClassName());
                    String className = lowerFirstCapse(clazz.getSimpleName());
                    Object bean = SpringUtil.getBean(className);
                    Method method = ReflectionUtils.findMethod(bean.getClass(), task.getMethodName());
                    ReflectionUtils.invokeMethod(method, bean);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        };
    }
    private List<HkSysTask> checkDataList(List<HkSysTask> list) {
        String errMsg="";
        for(int i=0;i<list.size();i++){
            if(!checkOneData(list.get(i)).equalsIgnoreCase("success")){
                errMsg+=list.get(i).getTaskName()+";";
                list.remove(list.get(i));
                i--;
            };
        }
        if(!StringUtils.isBlank(errMsg)){
            errMsg="未启动的任务:"+errMsg;
            log.error(errMsg);
        }
        return list;
    }
    private String checkOneData(HkSysTask task){
        String result="success";
        Class clazz= null;
        try {
            clazz = Class.forName(task.getClassName());
            //String className = lowerFirstCapse(clazz.getSimpleName());
            Object obj =SpringUtil.getBean(clazz);
            Method method = obj.getClass().getMethod(task.getMethodName(),null);
            String cron=task.getTaskCron();
            if(StringUtils.isBlank(cron)){
                result="定时任务启动错误,无cron:"+task.getTaskName();
                log.error(result);
            }
        } catch (ClassNotFoundException e) {
            result="定时任务启动错误,找不到类:"+task.getClassName()+ e.getMessage();
            log.error(result);
        } catch (NoSuchMethodException e) {
            result="定时任务启动错误,找不到方法,方法必须是public:"+task.getClassName()+";"+task.getMethodName()+";"+ e.getMessage();
            log.error(result);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return result;
    }
    /**
     * 转换首字母小写
     *
     * @param str
     * @return
     */
    public static String lowerFirstCapse(String str) {
        char[] chars = str.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
    /**
     * 启动定时任务
     * @param task
     * @param
     */
    public static void start(HkSysTask task){
        ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.schedule(getRunnable(task),getTrigger(task));
        scheduledFutureMap.put(task.getTaskUuid(),scheduledFuture);
        log.info("启动定时任务" + task.getId() );

    }
    /**
     * 取消定时任务
     * @param task
     */
    public static void cancel(HkSysTask task){

        ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(task.getId());

        if(scheduledFuture != null && !scheduledFuture.isCancelled()){
            scheduledFuture.cancel(Boolean.FALSE);
        }
        scheduledFutureMap.remove(task.getId());
        log.info("取消定时任务" + task.getId() );

    }
    /**
     * 编辑
     * @param task
     * @param
     */
    public static void reset(HkSysTask task){
        log.info("修改定时任务开始" + task.getId() );
        cancel(task);
        start(task);
        log.info("修改定时任务结束" + task.getId());
    }
}

4、定时执行的测试类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
......
    public void test(){
        iHkUserService.userTaskRun();
    }
......

5、console输出的日志

每天进步一点点!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
SpringBoot基于数据库的定时任务实现
在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现。
攻城狮的那点事
2019/12/27
1.5K0
SpringBoot基于数据库的定时任务实现
SpringBoot+MySQL实现动态定时任务
一个极简的基于springboot的动态定时任务demo,spring-context模块有对任务调度进行支持,本demo也是基于这个模块进行开发,功能相对简单,用户可以按需改造,比如添加运维界面,在界面上更加灵活的控制任务执行与更新。
科技新语
2025/05/09
1440
SpringBoot+MySQL实现动态定时任务
实践:SpringBoot实现定时任务的动态增删启停
我以为动态停启定时任务一般用quartz,没想到还可以通过ScheduledTaskRegistrar来拓展。但是分布式场景,建议还是用quartz吧!
乔戈里
2020/08/06
1.2K0
分布式定时任务框架之Uncode-Schedule框架源码分析
Uncode-Schedule是基于zookeeper的分布式任务调度组件,非常小巧,使用简单。 1.1. 它能够确保所有任务在集群中不重复,不遗漏的执行。 1.2. 单节点故障时,任务能够自动转移到其他节点继续执行。 1.3. 支持动态添加和删除任务。 1.4. 支持添加机器ip黑名单。 1.5. 支持手动执行任务。
lyb-geek
2018/07/26
1.3K0
SpringBoot 实现固定、动态定时任务 | 三种实现方式 | 附源代码
背景:📅 最近要用到这个定时任务,之前就简单使用注解的那种方式,需求一变化,就得重新修改。 就想到了动态定时任务,连接数据库来动态选择,这样确实解决了问题。 但是仍然有一个缺陷,就是没法设置任务的执行时间,无法做到像 QQ 发说说那样,给 xdm 祝福生日时,设定说说为晚上00:00发布。 本文就以上三点用自己的思路写了一个小Demo,希望对大家有所帮助。 👩‍💻 封面:来自于校园一角,秋意渐浓,思念渐深。 前言: 阅读完本文:🐱‍👓 知晓 SpringBoot 用注解如何实现定时任务 明白
宁在春
2022/10/31
7.8K0
SpringBoot 实现固定、动态定时任务 | 三种实现方式 | 附源代码
在Spring Boot中优雅的实现定时任务
在日常的项目开发中,往往会涉及到一些需要做到定时执行的代码,例如自动将超过24小时的未付款的单改为取消状态,自动将超过14天客户未签收的订单改为已签收状态等等,那么为了在Spring Boot中实现此类需求,我们要怎么做呢?
用户2781897
2020/11/02
1.2K0
在Spring Boot中优雅的实现定时任务
【SpringBoot】25、SpringBoot中使用Quartz管理定时任务
定时任务在系统中用到的地方很多,例如每晚凌晨的数据备份,每小时获取第三方平台的 Token 信息等等,之前我们都是在项目中规定这个定时任务什么时候启动,到时间了便会自己启动,那么我们想要停止这个定时任务的时候,就需要去改动代码,还得启停服务器,这是非常不友好的事情
全栈程序员站长
2022/11/01
6410
SpringBoot 定时任务动态管理通用解决方案
一、功能说明 SpringBoot的定时任务的加强工具,实现对SpringBoot原生的定时任务进行动态管理,完全兼容原生@Scheduled注解,无需对原本的定时任务进行修改 二、快速使用 具体的功能已经封装成SpringBoot-starter即插即用 <dependency>     <groupId>com.github.guoyixing</groupId>     <artifactId>spring-boot-starter-super-scheduled</artifactId>     <
java思维导图
2022/03/04
8880
基于Reids与AOP实现的定时任务锁-ScheduledLock
简单来说就是通过aop环绕切片将需要加锁的方法包起来,然后在执行前往redis中用setIfAbsent写入一个key,如果返回true,说明没有其他服务正在执行该方法,就继续执行,如果返回false,说明已经有其他服务正在执行该方法,就不执行。
Diuut
2022/11/22
7060
玩转定时任务,下次别为了修改定时任务而不断停止和重新启动项目了
相信大家在学习苍穹外卖的时候,就使用过定时任务。但是那个时候我们使用的定时任务的方式还比较死板:
程序员牛肉
2024/09/26
3500
玩转定时任务,下次别为了修改定时任务而不断停止和重新启动项目了
玩转 Spring Boot 集成篇(任务动态管理代码篇)
在日常项目研发中,定时任务可谓是必不可少的一环,如果面对任务执行周期固定,业务简单的场景,可直接使用 Spring Boot 内置注解方式实现任务;而如果考虑更为复杂的管理任务信息,在可以通过集成 Quartz 等开源轮子来助力业务研发。
一猿小讲
2022/02/25
2.3K9
玩转 Spring Boot 集成篇(任务动态管理代码篇)
Spring Boot 定时任务
首先在 SpringBoot 启动类加上 @EnableScheduling 启用定时任务。
数媒派
2022/12/01
3060
SpringBoot项目集成QuartzJob任务
在项目的实际场景中,我们经常会遇到一些任务需要每天、每周、或者固定时间去执行,所以在项目中加入Quartz框架,来更好的对这些事情做管理,只需要配置任务对应的CORN表达式,添加到任务里面即可让他自动化的实现对任务的管理。
芈亓
2023/09/26
6700
SpringBoot项目集成QuartzJob任务
SpringBoot动态配置定时任务cron(动态改变执行周期)
package model; public class SpringScheduledCron { private String cronId; private String cronKey; private String cronExpression; private String taskExplain; private String status; @Override public String toString() {
JQ实验室
2022/02/10
1.7K0
SpringBoot——动态多线程并发定时任务
怎么重新调用 refreshTask()方法:可以另外启一个任务实时监控任务表的数据变化。
默存
2022/06/24
3990
SpringBoot——动态多线程并发定时任务
SpringBoot中实现定时任务(Quartz)
Spring 3.0以后自带了 task 调度工具,使用比 Quartz简单方便,使用 @Scheduled 注解。
终有救赎
2023/10/22
6430
SpringBoot中实现定时任务(Quartz)
Spring Boot 定时任务与 xxl-job 灵活切换方案
在使用XXL—JOB的实现定时任务过程中,有时候可能由于部署环境的要求,就只能用Spring自带的实现方式。
终码一生
2024/06/18
5630
Spring Boot 定时任务与 xxl-job 灵活切换方案
动态更改 Spring 定时任务 Cron 表达式的优雅方案!
在 SpringBoot 项目中,我们可以通过@EnableScheduling注解开启调度任务支持,并通过@Scheduled注解快速地建立一系列定时任务。
java进阶架构师
2024/03/06
1.2K1
动态更改 Spring 定时任务 Cron 表达式的优雅方案!
SpringBoot中的定时任务的同步与异步
定时任务调度功能在我们的开发中是非常常见的,随便举几个例子:定时清除一些过期的数据,定时发送邮件等等,实现定时任务调度的方式也十分多样,本篇文章主要学习各种实现定时任务调度方式的优缺点,以便为日后选择的时候提供一定的参考。
烂猪皮
2023/09/04
1.1K0
SpringBoot中的定时任务的同步与异步
spring任务调度scheduled_golang 任务调度
除了TaskExecutor抽象之外,Spring 3.0还引用了任务调度接口 TaskScheduler,它提供了多种方法来调度将来某个时间点要运行的任务。
全栈程序员站长
2022/11/07
2K0
spring任务调度scheduled_golang 任务调度
推荐阅读
相关推荐
SpringBoot基于数据库的定时任务实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验