色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SpringBoot如何實現動態增刪啟停定時任務

Android編程精選 ? 來源:簡書 ? 作者:jessehua ? 2021-09-24 09:49 ? 次閱讀
在spring boot項目中,可以通過@EnableScheduling注解和@Scheduled注解實現定時任務,也可以通過SchedulingConfigurer接口來實現定時任務。但是這兩種方式不能動態添加、刪除、啟動、停止任務。

要實現動態增刪啟停定時任務功能,比較廣泛的做法是集成Quartz框架。但是本人的開發原則是:在滿足項目需求的情況下,盡量少的依賴其它框架,避免項目過于臃腫和復雜。

查看spring-context這個jar包中org.springframework.scheduling.ScheduledTaskRegistrar這個類的源代碼,發現可以通過改造這個類就能實現動態增刪啟停定時任務功能。

e8f20370-1085-11ec-8fb8-12bb97331649.jpg定時任務列表頁e90122f6-1085-11ec-8fb8-12bb97331649.jpg定時任務執行日志

添加執行定時任務的線程池配置類

@Configuration
publicclassSchedulingConfig{
@Bean
publicTaskSchedulertaskScheduler(){
ThreadPoolTaskSchedulertaskScheduler=newThreadPoolTaskScheduler();
//定時任務執行線程池核心線程數
taskScheduler.setPoolSize(4);
taskScheduler.setRemoveOnCancelPolicy(true);
taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");
returntaskScheduler;
}
}

添加ScheduledFuture的包裝類。ScheduledFuture是ScheduledExecutorService定時任務線程池的執行結果。

publicfinalclassScheduledTask{

volatileScheduledFuturefuture;

/**
*取消定時任務
*/
publicvoidcancel(){
ScheduledFuturefuture=this.future;
if(future!=null){
future.cancel(true);
}
}
}

添加Runnable接口實現類,被定時任務線程池調用,用來執行指定bean里面的方法。

publicclassSchedulingRunnableimplementsRunnable{

privatestaticfinalLoggerlogger=LoggerFactory.getLogger(SchedulingRunnable.class);

privateStringbeanName;

privateStringmethodName;

privateStringparams;

publicSchedulingRunnable(StringbeanName,StringmethodName){
this(beanName,methodName,null);
}

publicSchedulingRunnable(StringbeanName,StringmethodName,Stringparams){
this.beanName=beanName;
this.methodName=methodName;
this.params=params;
}

@Override
publicvoidrun(){
logger.info("定時任務開始執行- bean:{},方法:{},參數:{}",beanName,methodName,params);
longstartTime=System.currentTimeMillis();

try{
Objecttarget=SpringContextUtils.getBean(beanName);

Methodmethod=null;
if(StringUtils.isNotEmpty(params)){
method=target.getClass().getDeclaredMethod(methodName,String.class);
}else{
method=target.getClass().getDeclaredMethod(methodName);
}

ReflectionUtils.makeAccessible(method);
if(StringUtils.isNotEmpty(params)){
method.invoke(target,params);
}else{
method.invoke(target);
}
}catch(Exceptionex){
logger.error(String.format("定時任務執行異常- bean:%s,方法:%s,參數:%s ",beanName,methodName,params),ex);
}

longtimes=System.currentTimeMillis()-startTime;
logger.info("定時任務執行結束- bean:{},方法:{},參數:{},耗時:{}毫秒",beanName,methodName,params,times);
}

@Override
publicbooleanequals(Objecto){
if(this==o)returntrue;
if(o==null||getClass()!=o.getClass())returnfalse;
SchedulingRunnablethat=(SchedulingRunnable)o;
if(params==null){
returnbeanName.equals(that.beanName)&&
methodName.equals(that.methodName)&&
that.params==null;
}

returnbeanName.equals(that.beanName)&&
methodName.equals(that.methodName)&&
params.equals(that.params);
}

@Override
publicinthashCode(){
if(params==null){
returnObjects.hash(beanName,methodName);
}

returnObjects.hash(beanName,methodName,params);
}
}

添加定時任務注冊類,用來增加、刪除定時任務。

@Component
publicclassCronTaskRegistrarimplementsDisposableBean{

privatefinalMapscheduledTasks=newConcurrentHashMap<>(16);

@Autowired
privateTaskSchedulertaskScheduler;

publicTaskSchedulergetScheduler(){
returnthis.taskScheduler;
}

publicvoidaddCronTask(Runnabletask,StringcronExpression){
addCronTask(newCronTask(task,cronExpression));
}

publicvoidaddCronTask(CronTaskcronTask){
if(cronTask!=null){
Runnabletask=cronTask.getRunnable();
if(this.scheduledTasks.containsKey(task)){
removeCronTask(task);
}

this.scheduledTasks.put(task,scheduleCronTask(cronTask));
}
}

publicvoidremoveCronTask(Runnabletask){
ScheduledTaskscheduledTask=this.scheduledTasks.remove(task);
if(scheduledTask!=null)
scheduledTask.cancel();
}

publicScheduledTaskscheduleCronTask(CronTaskcronTask){
ScheduledTaskscheduledTask=newScheduledTask();
scheduledTask.future=this.taskScheduler.schedule(cronTask.getRunnable(),cronTask.getTrigger());

returnscheduledTask;
}


@Override
publicvoiddestroy(){
for(ScheduledTasktask:this.scheduledTasks.values()){
task.cancel();
}

this.scheduledTasks.clear();
}
}

添加定時任務示例類

@Component("demoTask")
publicclassDemoTask{
publicvoidtaskWithParams(Stringparams){
System.out.println("執行有參示例任務:"+params);
}

publicvoidtaskNoParams(){
System.out.println("執行無參示例任務");
}
}

定時任務數據庫表設計

添加定時任務實體類

publicclassSysJobPO{
/**
*任務ID
*/
privateIntegerjobId;
/**
*bean名稱
*/
privateStringbeanName;
/**
*方法名稱
*/
privateStringmethodName;
/**
*方法參數
*/
privateStringmethodParams;
/**
*cron表達式
*/
privateStringcronExpression;
/**
*狀態(1正常0暫停)
*/
privateIntegerjobStatus;
/**
*備注
*/
privateStringremark;
/**
*創建時間
*/
privateDatecreateTime;
/**
*更新時間
*/
privateDateupdateTime;

publicIntegergetJobId(){
returnjobId;
}

publicvoidsetJobId(IntegerjobId){
this.jobId=jobId;
}

publicStringgetBeanName(){
returnbeanName;
}

publicvoidsetBeanName(StringbeanName){
this.beanName=beanName;
}

publicStringgetMethodName(){
returnmethodName;
}

publicvoidsetMethodName(StringmethodName){
this.methodName=methodName;
}

publicStringgetMethodParams(){
returnmethodParams;
}

publicvoidsetMethodParams(StringmethodParams){
this.methodParams=methodParams;
}

publicStringgetCronExpression(){
returncronExpression;
}

publicvoidsetCronExpression(StringcronExpression){
this.cronExpression=cronExpression;
}

publicIntegergetJobStatus(){
returnjobStatus;
}

publicvoidsetJobStatus(IntegerjobStatus){
this.jobStatus=jobStatus;
}

publicStringgetRemark(){
returnremark;
}

publicvoidsetRemark(Stringremark){
this.remark=remark;
}

publicDategetCreateTime(){
returncreateTime;
}

publicvoidsetCreateTime(DatecreateTime){
this.createTime=createTime;
}

publicDategetUpdateTime(){
returnupdateTime;
}

publicvoidsetUpdateTime(DateupdateTime){
this.updateTime=updateTime;
}

}
booleansuccess=sysJobRepository.addSysJob(sysJob);
if(!success)
returnOperationResUtils.fail("新增失敗");
else{
if(sysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal())){
SchedulingRunnabletask=newSchedulingRunnable(sysJob.getBeanName(),sysJob.getMethodName(),sysJob.getMethodParams());
cronTaskRegistrar.addCronTask(task,sysJob.getCronExpression());
}
}

returnOperationResUtils.success();

修改定時任務,先移除原來的任務,再啟動新任務

booleansuccess=sysJobRepository.editSysJob(sysJob);
if(!success)
returnOperationResUtils.fail("編輯失敗");
else{
//先移除再添加
if(existedSysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal())){
SchedulingRunnabletask=newSchedulingRunnable(existedSysJob.getBeanName(),existedSysJob.getMethodName(),existedSysJob.getMethodParams());
cronTaskRegistrar.removeCronTask(task);
}

if(sysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal())){
SchedulingRunnabletask=newSchedulingRunnable(sysJob.getBeanName(),sysJob.getMethodName(),sysJob.getMethodParams());
cronTaskRegistrar.addCronTask(task,sysJob.getCronExpression());
}
}

returnOperationResUtils.success();

刪除定時任務

booleansuccess=sysJobRepository.deleteSysJobById(req.getJobId());
if(!success)
returnOperationResUtils.fail("刪除失敗");
else{
if(existedSysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal())){
SchedulingRunnabletask=newSchedulingRunnable(existedSysJob.getBeanName(),existedSysJob.getMethodName(),existedSysJob.getMethodParams());
cronTaskRegistrar.removeCronTask(task);
}
}

returnOperationResUtils.success();

定時任務啟動/停止狀態切換

if(existedSysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal())){
SchedulingRunnabletask=newSchedulingRunnable(existedSysJob.getBeanName(),existedSysJob.getMethodName(),existedSysJob.getMethodParams());
cronTaskRegistrar.addCronTask(task,existedSysJob.getCronExpression());
}else{
SchedulingRunnabletask=newSchedulingRunnable(existedSysJob.getBeanName(),existedSysJob.getMethodName(),existedSysJob.getMethodParams());
cronTaskRegistrar.removeCronTask(task);
}

添加實現了CommandLineRunner接口的SysJobRunner類,當spring boot項目啟動完成后,加載數據庫里狀態為正常的定時任務。

@Service
publicclassSysJobRunnerimplementsCommandLineRunner{

privatestaticfinalLoggerlogger=LoggerFactory.getLogger(SysJobRunner.class);

@Autowired
privateISysJobRepositorysysJobRepository;

@Autowired
privateCronTaskRegistrarcronTaskRegistrar;

@Override
publicvoidrun(String...args){
//初始加載數據庫里狀態為正常的定時任務
ListjobList=sysJobRepository.getSysJobListByStatus(SysJobStatus.NORMAL.ordinal());
if(CollectionUtils.isNotEmpty(jobList)){
for(SysJobPOjob:jobList){
SchedulingRunnabletask=newSchedulingRunnable(job.getBeanName(),job.getMethodName(),job.getMethodParams());
cronTaskRegistrar.addCronTask(task,job.getCronExpression());
}

logger.info("定時任務已加載完畢...");
}
}
}

工具類SpringContextUtils,用來從spring容器里獲取bean

@Component
publicclassSpringContextUtilsimplementsApplicationContextAware{

privatestaticApplicationContextapplicationContext;

@Override
publicvoidsetApplicationContext(ApplicationContextapplicationContext)
throwsBeansException{
SpringContextUtils.applicationContext=applicationContext;
}

publicstaticObjectgetBean(Stringname){
returnapplicationContext.getBean(name);
}

publicstaticTgetBean(ClassrequiredType){
returnapplicationContext.getBean(requiredType);
}

publicstaticTgetBean(Stringname,ClassrequiredType){
returnapplicationContext.getBean(name,requiredType);
}

publicstaticbooleancontainsBean(Stringname){
returnapplicationContext.containsBean(name);
}

publicstaticbooleanisSingleton(Stringname){
returnapplicationContext.isSingleton(name);
}

publicstaticClassgetType(Stringname){
returnapplicationContext.getType(name);
}
}

本文完,參考本文代碼可成功運行,親測!

(感謝閱讀,希望對你所有幫助)來源:www.jianshu.com/p/0f68936393fd
編輯:jq
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 源代碼
    +關注

    關注

    96

    文章

    2945

    瀏覽量

    66730
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14338
  • Boot
    +關注

    關注

    0

    文章

    149

    瀏覽量

    35823
  • SpringBoot
    +關注

    關注

    0

    文章

    173

    瀏覽量

    177

原文標題:告別硬編碼,SpringBoot實現動態增刪啟停定時任務

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux計劃任務介紹

    1.計劃任務定時任務)基本概述 1.什么是crond crond就是計劃任務,類似于我們平時生活中的鬧鐘。定點執行。 2.為什么要使用crond?crond主要是做一些周期性的任務
    的頭像 發表于 11-24 15:49 ?265次閱讀

    定時器技術:Air780E如何革新定時任務管理?

    今天講的是關于Air780E如何革新定時任務管理的內容,希望大家有所收獲。
    的頭像 發表于 11-07 13:50 ?217次閱讀
    <b class='flag-5'>定時</b>器技術:Air780E如何革新<b class='flag-5'>定時任務</b>管理?

    變頻器外接按鈕如何接線

    以下是變頻器外接按鈕接線的一般步驟: 確定變頻器的型號和規格,查閱其技術手冊以獲取接線圖和接線說明。 準備所需的工具和材料,包括螺絲刀、剝線鉗、接線端子、接線盒等。 關閉電源并斷開變頻器與電源
    的頭像 發表于 08-25 10:49 ?1644次閱讀

    linux定時任務的用法總結

    習慣了使用 windows 的計劃任務,使用 linux 中的 crontab 管理定時任務時很不適應。
    的頭像 發表于 08-14 18:16 ?838次閱讀
    linux<b class='flag-5'>定時任務</b>的用法總結

    ESP8266如何實現時間小于3us的定時任務?

    實現一個穩定的軟串口,現有的軟串口程序是通過中斷實現的,但中斷好像會被其他中斷打斷,導致數據丟失,定時器按文檔上的說法,只能大于50us,能不能實現時間小于3us的
    發表于 07-19 06:13

    PLC工程示例之步進電機

    電子發燒友網站提供《PLC工程示例之步進電機.rar》資料免費下載
    發表于 06-11 09:09 ?8次下載

    在物通博聯工業智能網關的本地配置界面(WEB)直接配置定時控制任務

    開關,可實現全年定時任務自動執行。在多個任務日期重疊時,可選執行高等級的還是并行執行。設有一個遠程和本地的控制點,默認為本地狀態,網關自己執行設置的任務,當用戶將改控制點切換為遠程時可
    的頭像 發表于 04-24 17:21 ?528次閱讀
    在物通博聯工業智能網關的本地配置界面(WEB)直接配置<b class='flag-5'>定時</b>控制<b class='flag-5'>任務</b>

    基于VC的三相異步電機系統的設計

    針對小功率三相異步電機的,當前國內外還較多地采用繼電器、接觸器等控制電器來實現自動控制。由于繼電接觸器控制系統是通過觸點的機械運動來通斷主、控回路,然而觸點因為電、機械和化學的原因易于磨損,并且在高沖擊、振蕩的工作環境下,觸
    發表于 02-15 17:21 ?512次閱讀
    基于VC的三相異步電機<b class='flag-5'>啟</b><b class='flag-5'>停</b>系統的設計

    使用TC21x的GPT實現1m計時器執行定時任務,怎么配置GTM和GPT?

    專家們好,我想使用TC21x的GPT實現1m計時器執行定時任務,不知道怎么配置GTM和GPT?
    發表于 02-06 06:47

    鴻蒙ArkUI開發-實現增刪Tab頁簽

    本文以瀏覽器中增加或刪除頁簽為例,實現Tabs中頁簽的增刪功能。
    的頭像 發表于 01-29 18:43 ?1578次閱讀
    鴻蒙ArkUI開發-<b class='flag-5'>實現</b><b class='flag-5'>增刪</b>Tab頁簽

    鴻蒙原生應用/元服務開發-長時任務

    概述 功能介紹 應用退至后臺后,對于在后臺需要長時間運行用戶可感知的任務,例如播放音樂、導航等。為防止應用進程被掛起,導致對應功能異常,可以申請長時任務,使應用在后臺長時間運行。申請長時任務后,系統
    發表于 01-09 10:52

    任務調度系統設計的核心邏輯

    Redis的讀寫性能極好,分布式鎖也比Quartz數據庫行級鎖更輕量級。當然Redis鎖也可以替換成Zookeeper鎖,也是同樣的機制。 在小型項目中,使用:定時任務框架(Quartz/Spring Schedule)和 分布式鎖(redis/zookeeper)有不錯的效果。
    的頭像 發表于 01-02 15:09 ?869次閱讀
    <b class='flag-5'>任務</b>調度系統設計的核心邏輯

    鴻蒙原生應用/元服務開發-短時任務

    \'@ohos.resourceschedule.backgroundTaskManager\'; 2.申請短時任務實現回調 et id; // 申請短時任務ID let delayTime; // 本次申請短
    發表于 12-28 16:13

    物通博聯工業智能網關實現PLC定時控制任務

    。 物通博聯工業智能網關不僅支持本地部署,同時也支持遠程部署,實現PLC程序的遠程讀寫。企業可通過添加定時控制任務,定義任務策略,設置設備定時
    的頭像 發表于 12-27 15:52 ?323次閱讀
    物通博聯工業智能網關<b class='flag-5'>實現</b>PLC<b class='flag-5'>定時</b>控制<b class='flag-5'>任務</b>

    多種一鍵的程序編寫方式你會幾種?

    對于剛入門的PLC新手來說,在沒有理解PLC CPU的掃描工作原理時對于行內偶爾提到的一鍵程序編寫總會有一定的難度!
    的頭像 發表于 12-27 11:32 ?719次閱讀
    多種一鍵<b class='flag-5'>啟</b><b class='flag-5'>停</b>的程序編寫方式你會幾種?
    主站蜘蛛池模板: 99精品国产福利在线观看| 亚洲日本乱码中文论理在线电影| 黑人寄宿羽月希产后奶水| 在线视频一区二区三区在线播放| 女同给老师下媚药| 国产精品丰满人妻AV麻豆| 亚洲无AV在线中文字幕| 欧美人与动牲交A免费| 国产精品永久AV无码视频| 在线免费福利| 日韩成人黄色| 精品亚洲麻豆1区2区3区| avav去吧| 亚洲第一国产| 嫩交18xxxx| 国产欧美一区二区三区免费| 最近中文字幕MV免费高清视频8| 日韩成人在线视频| 久久国产欧美| 粗壮挺进邻居人妻无码| 艳照门在线观看| 人妻插B视频一区二区三区| 亚洲午夜性春猛交XXXX| 美国兽皇zoo在线播放| 国产99久久久国产精品免费看 | 三男强一女90分钟在线观看| 黄色三级视频在线| SORA是什么意思| 亚洲视频免费在线观看| 青青草原国产在线观看| 吉吉影音先锋av资源网| 超碰超碰视频在线观看| 伊人久综合| 四虎国产精品高清在线观看| 蓝男色gay| 国产人妻久久久精品麻豆| 99久久久久亚洲AV无码| 亚洲日产2020乱码草莓毕| 色狠狠一区二区| 美女视频黄色的| 国模啪啪久久久久久久|