溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何實現(xiàn)集成定時任務(wù)SchedulingConfigurer

發(fā)布時間:2021-10-13 10:11:52 來源:億速云 閱讀:149 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“如何實現(xiàn)集成定時任務(wù)SchedulingConfigurer”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

背景:

      項目需要啟動一個定時執(zhí)行的任務(wù),該任務(wù)的執(zhí)行可以隨時停止執(zhí)行,要求在數(shù)據(jù)庫配置執(zhí)行規(guī)律。

調(diào)研:使用scheduling定時任務(wù)與springboot集成;

實例:

第一步:創(chuàng)建一個數(shù)據(jù)表,保存執(zhí)行的任務(wù)           

/*DDL 信息*/------------

CREATE TABLE `hk_sys_task` (
  `id` bigint(21) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `task_uuid` varchar(50) DEFAULT NULL COMMENT '任務(wù)UUID',
  `task_name` varchar(50) DEFAULT NULL COMMENT '任務(wù)名稱',
  `task_cron` varchar(50) DEFAULT NULL COMMENT '任務(wù)定時表達式',
  `class_name` varchar(100) DEFAULT NULL COMMENT '任務(wù)類',
  `method_name` varchar(100) DEFAULT NULL COMMENT '任務(wù)方法',
  `task_type` int(1) DEFAULT NULL COMMENT '任務(wù)類型',
  `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

如何實現(xiàn)集成定時任務(wù)SchedulingConfigurer

2、創(chuàng)建springboot的SpringUtil用戶獲取bean

/**
 * @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配置成功,在普通類可以通過調(diào)用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、配置執(zhí)行任務(wù)的類SysTaskConfig

/**
 * @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<>();

    //從數(shù)據(jù)庫里取得所有要執(zhí)行的定時任務(wù)
    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("定時任務(wù)啟動,預計啟動任務(wù)數(shù)量={},; time={}",allTasks.size(),LocalDateTime.now());

        //校驗數(shù)據(jù)(這個步驟主要是為了打印日志,可以省略)
        checkDataList(allTasks);

        //通過校驗的數(shù)據(jù)執(zhí)行定時任務(wù)
        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("定時任務(wù)啟動錯誤:" + allTasks.get(i).getClassName() + ";" + allTasks.get(i).getMethodName() + ";" + e.getMessage());
                }
            }
        }
        log.info("定時任務(wù)實際啟動數(shù)量="+count+"; time="+LocalDateTime.now());
    }
    private static Trigger getTrigger(HkSysTask task){
        return new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                //將Cron 0/1 * * * * ? 輸入取得下一次執(zhí)行的時間
                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="未啟動的任務(wù):"+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="定時任務(wù)啟動錯誤,無cron:"+task.getTaskName();
                log.error(result);
            }
        } catch (ClassNotFoundException e) {
            result="定時任務(wù)啟動錯誤,找不到類:"+task.getClassName()+ e.getMessage();
            log.error(result);
        } catch (NoSuchMethodException e) {
            result="定時任務(wù)啟動錯誤,找不到方法,方法必須是public:"+task.getClassName()+";"+task.getMethodName()+";"+ e.getMessage();
            log.error(result);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return result;
    }
    /**
     * 轉(zhuǎn)換首字母小寫
     *
     * @param str
     * @return
     */
    public static String lowerFirstCapse(String str) {
        char[] chars = str.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
    /**
     * 啟動定時任務(wù)
     * @param task
     * @param
     */
    public static void start(HkSysTask task){
        ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.schedule(getRunnable(task),getTrigger(task));
        scheduledFutureMap.put(task.getTaskUuid(),scheduledFuture);
        log.info("啟動定時任務(wù)" + task.getId() );

    }
    /**
     * 取消定時任務(wù)
     * @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("取消定時任務(wù)" + task.getId() );

    }
    /**
     * 編輯
     * @param task
     * @param
     */
    public static void reset(HkSysTask task){
        log.info("修改定時任務(wù)開始" + task.getId() );
        cancel(task);
        start(task);
        log.info("修改定時任務(wù)結(jié)束" + task.getId());
    }
}

4、定時執(zhí)行的測試類

......
    public void test(){
        iHkUserService.userTaskRun();
    }
......

5、console輸出的日志

如何實現(xiàn)集成定時任務(wù)SchedulingConfigurer

“如何實現(xiàn)集成定時任務(wù)SchedulingConfigurer”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI