<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
基於上篇程式,做了一版動態定時程式,然後發現這個定時程式需要在下次執行的時候會載入新的時間,所以如果改了定時程式不能馬上觸發,所以想到一種方法,在儲存定時程式的時候將cron表示式傳過去,然後觸發定時程式,下面看看怎麼實現
開發環境
開發工具
基於上一版進行改進:
加上ThreadPoolTaskScheduler,支援同步和非同步兩種方式:
import lombok.extern.slf4j.Slf4j; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; @Configuration @Slf4j public class ScheduleConfig implements SchedulingConfigurer , AsyncConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); } @Bean(destroyMethod="shutdown" , name = "taskScheduler") public ThreadPoolTaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.setThreadNamePrefix("itemTask-"); scheduler.setAwaitTerminationSeconds(600); scheduler.setWaitForTasksToCompleteOnShutdown(true); return scheduler; } @Bean(name = "asyncExecutor") public ThreadPoolTaskExecutor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setQueueCapacity(1000); executor.setKeepAliveSeconds(600); executor.setMaxPoolSize(20); executor.setThreadNamePrefix("itemAsyncTask-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } @Override public Executor getAsyncExecutor() { return asyncExecutor(); } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (throwable, method, objects) -> { log.error("非同步任務異常,message {} , method {} , params" , throwable , method , objects); }; } }
加上一個SchedulerTaskJob
介面:
public interface SchedulerTaskJob{ void executeTask(); }
AbstractScheduler 抽象類,提供基本的功能
import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.TriggerContext; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Date; @Slf4j @Component @Data public abstract class AbstractScheduler implements SchedulerTaskJob{ @Resource(name = "taskScheduler") private ThreadPoolTaskScheduler threadPoolTaskScheduler; @Override public void executeTask() { String cron = getCronString(); Runnable task = () -> { // 執行業務 doBusiness(); }; Trigger trigger = new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) { CronTrigger trigger; try { trigger = new CronTrigger(cron); return trigger.nextExecutionTime(triggerContext); } catch (Exception e) { log.error("cron表示式異常,已經啟用預設設定"); // 設定cron表示式異常,執行預設的表示式 trigger = new CronTrigger(getDefaultCron()); return trigger.nextExecutionTime(triggerContext); } } }; threadPoolTaskScheduler.schedule(task , trigger); } protected abstract String getCronString(); protected abstract void doBusiness(); protected abstract String getDefaultCron(); }
實現類,基於自己的業務實現,然後事項抽象類,通過模板模式進行程式設計
import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.time.LocalDateTime; @Service @Slf4j @Data public class ItemSyncScheduler extends AbstractScheduler { @Value("${configtask.default.itemsync}") private String defaultCron ; private String cronString ; @Override protected String getCronString() { if (StrUtil.isNotBlank(cronString)) return cronString; SyncConfigModel configModel = syncConfigService.getOne(Wrappers.<SyncConfigModel>lambdaQuery() .eq(SyncConfigModel::getBizType, 1) .last("limit 1")); if (configModel == null) return defaultCron; return configModel.getCronStr(); } @Override protected void doBusiness() { log.info("執行業務..."); log.info("執行時間:{}" , LocalDateTime.now()); // 執行業務 } @Override protected String getDefaultCron() { return defaultCron; } }
如果更改了cron表示式,程式不會馬上觸發,所以直接開放一個介面出來,呼叫的時候,設定最新的表示式,然後重新呼叫定時程式
import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class ItemSchedulerController { private ItemSyncScheduler itemSyncScheduler; @Autowired public ItemSchedulerController(ItemSyncScheduler itemSyncScheduler) { this.itemSyncScheduler= itemSyncScheduler; } @GetMapping(value = "/updateItemCron") @ApiOperation(value = "更新cron表示式") public void updateItemCron(@RequestParam("cronString") String cronString) { log.info("更新cron表示式..."); log.info("cronString:{}" , cronString); itemSyncScheduler.setCronString(cronString); itemSyncScheduler.executeTask(); } }
實現CommandLineRunner ,實現Springboot啟動載入
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.annotation.Resource; @Component @Order(1) public class SchedulerTaskRunner implements CommandLineRunner { private ItemSyncScheduler itemSyncScheduler; @Autowired public SchedulerTaskRunner(ItemSyncScheduler itemSyncScheduler) { this.itemSyncScheduler= itemSyncScheduler; } @Override public void run(String... args) throws Exception { itemSyncScheduler.executeTask(); } }
基於上一版定時程式的問題,做了改進,加上了執行緒池和做到了動態觸發,網上的資料很多都是直接寫明使用SchedulingConfigurer
來實現動態定時程式,不過很多都寫明場景,本文通過實際,寫明實現方法,本文是在儲存定時程式的時候,設定最新的cron表示式,調一下介面重新載入,還可以使用canal等中介軟體監聽資料表,如果改了就再設定cron表示式,然後觸發程式
到此這篇關於SpringBoot動態定時功能實現方案詳解的文章就介紹到這了,更多相關SpringBoot動態定時內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45