chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpringBoot如何實(shí)現(xiàn)動態(tài)增刪啟停定時任務(wù)

Android編程精選 ? 來源:簡書 ? 作者:jessehua ? 2021-09-24 09:49 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在spring boot項(xiàng)目中,可以通過@EnableScheduling注解和@Scheduled注解實(shí)現(xiàn)定時任務(wù),也可以通過SchedulingConfigurer接口來實(shí)現(xiàn)定時任務(wù)。但是這兩種方式不能動態(tài)添加、刪除、啟動、停止任務(wù)。

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

查看spring-context這個jar包中org.springframework.scheduling.ScheduledTaskRegistrar這個類的源代碼,發(fā)現(xiàn)可以通過改造這個類就能實(shí)現(xiàn)動態(tài)增刪啟停定時任務(wù)功能。

e8f20370-1085-11ec-8fb8-12bb97331649.jpg定時任務(wù)列表頁e90122f6-1085-11ec-8fb8-12bb97331649.jpg定時任務(wù)執(zhí)行日志

添加執(zhí)行定時任務(wù)的線程池配置類

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

添加ScheduledFuture的包裝類。ScheduledFuture是ScheduledExecutorService定時任務(wù)線程池的執(zhí)行結(jié)果。

publicfinalclassScheduledTask{

volatileScheduledFuturefuture;

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

添加Runnable接口實(shí)現(xiàn)類,被定時任務(wù)線程池調(diào)用,用來執(zhí)行指定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("定時任務(wù)開始執(zhí)行- bean:{},方法:{},參數(shù):{}",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("定時任務(wù)執(zhí)行異常- bean:%s,方法:%s,參數(shù):%s ",beanName,methodName,params),ex);
}

longtimes=System.currentTimeMillis()-startTime;
logger.info("定時任務(wù)執(zhí)行結(jié)束- bean:{},方法:{},參數(shù):{},耗時:{}毫秒",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);
}
}

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

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

添加定時任務(wù)示例類

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

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

定時任務(wù)數(shù)據(jù)庫表設(shè)計

添加定時任務(wù)實(shí)體類

publicclassSysJobPO{
/**
*任務(wù)ID
*/
privateIntegerjobId;
/**
*bean名稱
*/
privateStringbeanName;
/**
*方法名稱
*/
privateStringmethodName;
/**
*方法參數(shù)
*/
privateStringmethodParams;
/**
*cron表達(dá)式
*/
privateStringcronExpression;
/**
*狀態(tài)(1正常0暫停)
*/
privateIntegerjobStatus;
/**
*備注
*/
privateStringremark;
/**
*創(chuàng)建時間
*/
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();

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

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();

刪除定時任務(wù)

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();

定時任務(wù)啟動/停止?fàn)顟B(tài)切換

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);
}

添加實(shí)現(xiàn)了CommandLineRunner接口的SysJobRunner類,當(dāng)spring boot項(xiàng)目啟動完成后,加載數(shù)據(jù)庫里狀態(tài)為正常的定時任務(wù)。

@Service
publicclassSysJobRunnerimplementsCommandLineRunner{

privatestaticfinalLoggerlogger=LoggerFactory.getLogger(SysJobRunner.class);

@Autowired
privateISysJobRepositorysysJobRepository;

@Autowired
privateCronTaskRegistrarcronTaskRegistrar;

@Override
publicvoidrun(String...args){
//初始加載數(shù)據(jù)庫里狀態(tài)為正常的定時任務(wù)
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("定時任務(wù)已加載完畢...");
}
}
}

工具類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);
}
}

本文完,參考本文代碼可成功運(yùn)行,親測!

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

    關(guān)注

    96

    文章

    2953

    瀏覽量

    69608
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    341

    瀏覽量

    15759
  • Boot
    +關(guān)注

    關(guān)注

    0

    文章

    154

    瀏覽量

    37463
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    177

    瀏覽量

    622

原文標(biāo)題:告別硬編碼,SpringBoot實(shí)現(xiàn)動態(tài)增刪啟停定時任務(wù)

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何使用SpringBoot、Vue2.0、MySQL開發(fā)一套云診所系統(tǒng)?

    (RESTful)等。 對于云診所系統(tǒng),SpringBoot可以用于實(shí)現(xiàn)患者管理、預(yù)約掛號、電子病歷、藥品管理、收費(fèi)管理等核心功能。 前端:V
    的頭像 發(fā)表于 11-27 16:02 ?94次閱讀
    如何使用<b class='flag-5'>SpringBoot</b>、Vue2.0、MySQL開發(fā)一套云診所系統(tǒng)?

    自動空調(diào)節(jié)能 25V 470μF Heyue車規(guī)插件鋁電解電容 能效提升 18%

    25V 470μF車規(guī)插件鋁電解電容在自動空調(diào)節(jié)能中,通過優(yōu)化電源管理,可將能效提升約18% ,其核心作用體現(xiàn)在以下三方面: 一、技術(shù)原理:低ESR與快速充放電支撐節(jié)能 低ESR特性減少能量損耗
    的頭像 發(fā)表于 10-22 15:17 ?176次閱讀
    自動空調(diào)<b class='flag-5'>啟</b><b class='flag-5'>停</b>節(jié)能 25V 470μF Heyue車規(guī)插件鋁電解電容 能效提升 18%

    車規(guī)鋁電解電容:緩解汽車系統(tǒng)供電波動的實(shí)用組件

    車規(guī)鋁電解電容是緩解汽車系統(tǒng)供電波動的核心組件,其通過材料創(chuàng)新、結(jié)構(gòu)優(yōu)化和智能控制,有效解決了停過程中電壓驟降、電流沖擊和電磁干擾等關(guān)鍵問題,顯著提升了系統(tǒng)可靠性和用戶體驗(yàn)。以下從技術(shù)
    的頭像 發(fā)表于 10-17 15:34 ?151次閱讀

    求一個multisim驅(qū)動電路的電路仿真

    我需要一個驅(qū)動電路的電路仿真,我希望可以把文件直接發(fā)給我,用的元器件也告訴我,感謝???。
    發(fā)表于 10-11 10:37

    御控物聯(lián)網(wǎng)遠(yuǎn)程控制水泵智能自控解決方案

    預(yù)測和故障自愈;3)數(shù)據(jù)可視化分析,優(yōu)化維護(hù)周期。系統(tǒng)采用工業(yè)級硬件和加密傳輸,適用于農(nóng)業(yè)灌溉、城市排水和工業(yè)供水等場景,可降低能耗40%,減少維護(hù)成本80萬元/年,實(shí)現(xiàn)精準(zhǔn)用水和防澇預(yù)警。
    的頭像 發(fā)表于 09-08 10:48 ?476次閱讀

    Crontab定時任務(wù)完全指南

    在凌晨3點(diǎn),當(dāng)大多數(shù)人還在熟睡時,一位運(yùn)維工程師的手機(jī)突然響起——線上數(shù)據(jù)庫備份失敗了。他匆忙起床,打開電腦,手動執(zhí)行備份腳本,整個過程耗時2小時。這樣的場景,在我剛?cè)胄袝r經(jīng)常遇到。直到我真正掌握了crontab定時任務(wù),才徹底擺脫了"人肉運(yùn)維"的窘境。
    的頭像 發(fā)表于 09-05 10:03 ?563次閱讀

    節(jié)能生產(chǎn)PLC數(shù)據(jù)采集解決方案

    某注塑廠原有多臺注塑機(jī)采用統(tǒng)一時間模式,導(dǎo)致用電高峰時段設(shè)備全開,電費(fèi)成本居高不下。同時,傳統(tǒng)人工排程效率低,無法根據(jù)訂單優(yōu)先級和設(shè)備狀態(tài)動態(tài)調(diào)整生產(chǎn)計劃,造成能源浪費(fèi)與產(chǎn)能失衡。亟需一套智能化、可視化的數(shù)據(jù)采集與排程系統(tǒng),
    的頭像 發(fā)表于 09-02 18:14 ?509次閱讀
    節(jié)能生產(chǎn)PLC數(shù)據(jù)采集解決方案

    Task任務(wù):LuatOS實(shí)現(xiàn)任務(wù)級并發(fā)”的核心引擎

    Task任務(wù)通過其強(qiáng)大的并發(fā)處理能力,使LuatOS能夠在單線程環(huán)境中模擬多線程執(zhí)行,通過協(xié)程的掛起與恢復(fù)機(jī)制,實(shí)現(xiàn)任務(wù)級的并行操作,顯著提升系統(tǒng)效能。 sys核心庫是LuatOS運(yùn)行框架庫,也是
    的頭像 發(fā)表于 08-28 13:49 ?322次閱讀
    Task<b class='flag-5'>任務(wù)</b>:LuatOS<b class='flag-5'>實(shí)現(xiàn)</b>“<b class='flag-5'>任務(wù)</b>級并發(fā)”的核心引擎

    電梯控制板里的直插鋁電解電容:頻繁中保持穩(wěn)定的 “垂直衛(wèi)士”

    在現(xiàn)代電梯控制系統(tǒng)中,直插鋁電解電容扮演著至關(guān)重要的角色。這些看似普通的電子元件,實(shí)際上承擔(dān)著保障電梯安全穩(wěn)定運(yùn)行的重任。特別是在電梯頻繁的工作環(huán)境下,直插鋁電解電容的性能直接關(guān)系到整個控制系統(tǒng)
    的頭像 發(fā)表于 08-25 18:22 ?608次閱讀

    使用C#實(shí)現(xiàn)西門子PLC數(shù)據(jù)定時讀取保存

    在平時開發(fā)中,我們時常會遇到需要后臺靜默運(yùn)行的應(yīng)用場景,這些程序不需要用戶的直接操作或界面展示,而是專注于定時任務(wù)的執(zhí)行。比如說,我們需要定期從西門子PLC(可編程邏輯控制器)中讀取數(shù)據(jù)并進(jìn)行保存,以便后續(xù)分析使用。
    的頭像 發(fā)表于 08-07 16:17 ?2123次閱讀
    使用C#<b class='flag-5'>實(shí)現(xiàn)</b>西門子PLC數(shù)據(jù)<b class='flag-5'>定時</b>讀取保存

    冠坤臺系電容 —— 汽車裝置的 “能量小助手”

    電容的創(chuàng)新應(yīng)用延伸至汽車系統(tǒng)這一特殊場景,以“能量小助手”的角色助力現(xiàn)代汽車實(shí)現(xiàn)更高效的能源管理。 **系統(tǒng)的能量挑戰(zhàn)與電容的技術(shù)突
    的頭像 發(fā)表于 08-04 17:02 ?689次閱讀

    智能時代,DF MAX停電池“蓄勢待發(fā)”

    隨著城市交通擁堵日益加劇,系統(tǒng)的重要性正變得前所未有的突出。據(jù)相關(guān)統(tǒng)計,北京市中心區(qū)的平均擁堵率已達(dá) 43.6%,而上海更是高達(dá) 46.1%。在這種“慢走快”的道路環(huán)境中,車輛頻繁在紅綠燈前
    的頭像 發(fā)表于 06-05 13:29 ?351次閱讀

    DF MAX-AGM停電池:技術(shù)創(chuàng)新引領(lǐng)綠色駕駛新時代

    汽車技術(shù)從最初的市場試探到如今的主流配置,展現(xiàn)了汽車工業(yè)在環(huán)保與實(shí)用性之間的卓越平衡。這項(xiàng)技術(shù)不僅為全球節(jié)能減排作出重要貢獻(xiàn),還為用戶帶來了更經(jīng)濟(jì)、更舒適的駕駛體驗(yàn)。 ? 現(xiàn)代
    的頭像 發(fā)表于 05-09 15:34 ?440次閱讀

    吸塵器啟動不穩(wěn)定?硬件、算法、系統(tǒng)集成三大策略,穩(wěn)定20000次--其利天下

    市面上吸塵器方案一般會遇到啟動不穩(wěn)定異常,那么針對這個問題,其利天下的12V手持車載吸塵器方案,做到了不同紋波干擾下 20000次無異常的成績。 解決吸塵器驅(qū)動中的電源干擾問題時,主要從硬件設(shè)計、控制算法優(yōu)化以及系統(tǒng)集成三個方面入手,以下是具體措施:
    的頭像 發(fā)表于 04-24 17:17 ?1280次閱讀
    吸塵器啟動不穩(wěn)定?硬件、算法、系統(tǒng)集成三大策略,穩(wěn)定<b class='flag-5'>啟</b><b class='flag-5'>停</b>20000次--其利天下

    【第四章 定時任務(wù)】手把手教你玩轉(zhuǎn)新版正點(diǎn)原子云

    【第四章 定時任務(wù)】手把手教你玩轉(zhuǎn)新版正點(diǎn)原子云 承接上篇,除了報警聯(lián)動這個功能,原子云還有一個特色功能也是各開發(fā)者喜歡用的,定時任務(wù)功能。 【正點(diǎn)原子】云平臺:原子云(點(diǎn)擊登錄原子云) 前言
    發(fā)表于 03-13 10:19