Springboot-admin怎么整合Quartz实现动态管理定时任务


这篇文章主要介绍“Springboot-admin怎么整合Quartz实现动态管理定时任务”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Springboot-admin怎么整合Quartz实现动态管理定时任务”文章能帮助大家解决问题。

boot-admin整合Quartz实现动态管理定时任务

淄博烧烤爆红出了圈,当你坐在八大局的烧烤摊,面前是火炉、烤串、小饼和蘸料,音乐响起,啤酒倒满,烧烤灵魂的party即将开场的时候,你系统中的Scheduler(调试器),也自动根据设定的Trigger(触发器),从容优雅的启动了一系列的Job(后台定时任务)。工作一切早有安排,又何须费心劳神呢?因为boot-admin早已将Quartz这块肉串在了烤签上!

Quartz是一款Java编写的开源任务调度框架,同时它也是Spring默认的任务调度框架。它的作用其实类似于Timer定时器以及ScheduledExecutorService调度线程池,当然Quartz作为一个独立的任务调度框架表现更为出色,功能更强大,能够定义更为复杂的执行规则。
boot-admin 是一款采用前后端分离模式、基于 SpringCloud 微服务架构 + vue-element-admin 的 SaaS 后台管理框架。
那么boot-admin怎样才能将Quartz串成串呢?一共分三步:

加入依赖

<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.2</version></dependency>

前端整合

vue页面以el-table作为任务的展示控件,串起任务的创建、修改、删除、挂起、恢复、状态查看等功能。

vue页面

<template><divclass="app-container"><!--功能按钮区--><divclass="clpd-5bg-1bk-gray"><divalign="left"><el-buttonsize="mini"type="primary"@click="search()">查询</el-button><el-buttonsize="mini"type="primary"@click="handleadd()">添加</el-button></div><divalign="right"><!--分页控件--><div><el-pagination:current-page="BaseTableData.page.currentPage":page-sizes="[5,10,20,50,100,500]":page-size="BaseTableData.page.pageSize"layout="total,sizes,prev,pager,next,jumper":total="BaseTableData.page.total"@size-change="handlePageSizeChange"@current-change="handlePageCurrentChange"/></div><!--分页控件--></div></div><!--功能按钮区--><!--表格--><el-tablemax-height="100%":data="BaseTableData.table":border="true"><el-table-columntype="index":index="indexMethod"/><el-table-columnprop="jobName"label="任务名称"width="100px"/><el-table-columnprop="jobGroup"label="任务所在组"width="100px"/><el-table-columnprop="jobClassName"label="任务类名"/><el-table-columnprop="cronExpression"label="表达式"width="120"/><el-table-columnprop="timeZoneId"label="时区"width="120"/><el-table-columnprop="startTime"label="开始"width="120":formatter="(row,column,cellValue)=>dateTimeColFormatter(row,column,cellValue)"/><el-table-columnprop="nextFireTime"label="下次"width="120":formatter="(row,column,cellValue)=>dateTimeColFormatter(row,column,cellValue)"/><el-table-columnprop="previousFireTime"label="上次"width="120":formatter="(row,column,cellValue)=>dateTimeColFormatter(row,column,cellValue)"/><el-table-columnprop="triggerState"label="状态"width="80"><templateslot-scope="scope"><pv-if="scope.row.triggerState=='NORMAL'">等待</p><pv-if="scope.row.triggerState=='PAUSED'">暂停</p><pv-if="scope.row.triggerState=='NONE'">删除</p><pv-if="scope.row.triggerState==&#39PLETE'">结束</p><pv-if="scope.row.triggerState=='ERROR'">错误</p><pv-if="scope.row.triggerState=='BLOCKED'">阻塞</p></template></el-table-column><el-table-columnlabel="操作"width="220px"><templateslot-scope="scope"><el-buttontype="warning"size="least"title="挂起"@click="handlePause(scope.row)">挂起</el-button><el-buttontype="primary"size="least"title="恢复"@click="handleResume(scope.row)">恢复</el-button><el-buttontype="danger"size="least"title="删除"@click="handleDelete(scope.row)">删除</el-button><el-buttontype="success"size="least"title="修改"@click="handleUpdate(scope.row)">修改</el-button></template></el-table-column></el-table><!--表格--><!--主表单弹出窗口--><el-dialogv-cloaktitle="维护":visible.sync="InputBaseInfoDialogData.dialogVisible":close-on-click-modal="InputBaseInfoDialogData.showCloseButton"top="5vh":show-close="InputBaseInfoDialogData.showCloseButton":fullscreen="InputBaseInfoDialogData.dialogFullScreen"><!--弹窗头部header--><divslot="title"><divalign="left"><h4>定时任务管理</h4></div><divalign="right"><el-buttontype="text"title="全屏显示"@click="resizeInputBaseInfoDialogMax()"><iclass="el-icon-arrow-up"/></el-button><el-buttontype="text"title="以弹出窗口形式显示"@click="resizeInputBaseInfoDialogNormal()"><iclass="el-icon-arrow-down"/></el-button><el-buttontype="text"title="关闭"@click="closeInputBaseInfoDialog()"><iclass="el-icon-error"/></el-button></div></div><!--弹窗头部header--><!--弹窗表单--><el-formref="InputBaseInfoForm":status-icon="InputBaseInfoDialogData.statusIcon":model="InputBaseInfoDialogData.data"class="demo-ruleForm"><el-form-itemlabel="原任务名称":label-width="InputBaseInfoDialogData.formLabelWidth"prop="jobName">{{InputBaseInfoDialogData.data.oldJobName}}【修改任务时使用】</el-form-item><el-form-itemlabel="原任务分组":label-width="InputBaseInfoDialogData.formLabelWidth"prop="jobGroup">{{InputBaseInfoDialogData.data.oldJobGroup}}【修改任务时使用】</el-form-item><el-form-itemlabel="任务名称":label-width="InputBaseInfoDialogData.formLabelWidth"prop="jobName"><el-inputv-model="InputBaseInfoDialogData.data.jobName"autoplete="off"/></el-form-item><el-form-itemlabel="任务分组":label-width="InputBaseInfoDialogData.formLabelWidth"prop="jobGroup"><el-inputv-model="InputBaseInfoDialogData.data.jobGroup"autoplete="off"/></el-form-item><el-form-itemlabel="类名":label-width="InputBaseInfoDialogData.formLabelWidth"prop="jobClassName"><el-inputv-model="InputBaseInfoDialogData.data.jobClassName"autoplete="off"/></el-form-item><el-form-itemlabel="表达式":label-width="InputBaseInfoDialogData.formLabelWidth"prop="cronExpression"><el-inputv-model="InputBaseInfoDialogData.data.cronExpression"autoplete="off"/></el-form-item></el-form><!--弹窗表单--><!--弹窗尾部footer--><divslot="footer"class="dialog-footer"><el-buttontype="primary"@click="saveInputBaseInfoForm()">保存</el-button></div><!--弹窗尾部footer--></el-dialog><!--弹出窗口--><!--查看场所弹出窗口--><el-dialogv-cloaktitle="修改任务":visible.sync="ViewBaseInfoDialogData.dialogVisible":close-on-click-modal="ViewBaseInfoDialogData.showCloseButton"top="5vh":show-close="ViewBaseInfoDialogData.showCloseButton":fullscreen="ViewBaseInfoDialogData.dialogFullScreen"><!--弹窗头部header--><divslot="title"><divalign="left"><h4>修改任务</h4></div><divalign="right"><el-buttontype="text"@click="dialogResize('ViewBaseInfoDialog',true)"><iclass="el-icon-arrow-up"title="全屏显示"/></el-button><el-buttontype="text"@click="dialogResize('ViewBaseInfoDialog',false)"><iclass="el-icon-arrow-down"title="以弹出窗口形式显示"/></el-button><el-buttontype="text"@click="dialogClose('ViewBaseInfoDialog')"><iclass="el-icon-error"title="关闭"/></el-button></div></div><!--弹窗头部header--><!--弹窗表单--><el-formref="ViewBaseInfoForm":status-icon="ViewBaseInfoDialogData.statusIcon":model="ViewBaseInfoDialogData.data"class="demo-ruleForm"><el-form-itemlabel="表达式":label-width="ViewBaseInfoDialogData.formLabelWidth"prop="cronExpression">{{this.BaseTableData.currentRow.cronExpression}}</el-form-item></el-form><!--弹窗表单--></el-dialog></div></template><script>import{getBlankJob,fetchJobPage,getUpdateObject,saveJob,pauseJob,resumeJob,deleteJob}from'@/api/job'exportdefault{name:'Jobmanage',data:function(){return{/***后台服务忙,防止重复提交的控制变量**/ServiceRunning:false,/***表格和分页组件**/BaseTableData:{currentRow:{},page:{currentPage:1,pageSize:20,pageNum:1,pages:1,size:5,total:1},/***主表格数据**/table:[],/***勾选选中的数据**/selected:[]},InputBaseInfoDialogData:{data:{},dialogVisible:false,dialogFullScreen:false,formLabelWidth:'180px',showCloseButton:false,statusIcon:true},ViewBaseInfoDialogData:{cronExpression:'',dialogVisible:false,dialogFullScreen:true,formLabelWidth:'180px'}}},/***初始化自动执行查询表格数据--不用调整**/mounted:function(){this.loadTableData()},methods:{/***查询---------根据实际调整参数*/asyncloadTableData(){if(this.ServiceRunning){this.$message({message:'请不要重复点击。',type:'warning'})return}this.ServiceRunning=trueconstresponse=awaitfetchJobPage(this.BaseTableData.page)if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}const{data}=responsethis.BaseTableData.page.total=data.totalthis.BaseTableData.table=data.recordsthis.ServiceRunning=false},/***每页大小调整事件*@paramval*/handlePageSizeChange(val){if(val!=this.BaseTableData.page.pageSize){this.BaseTableData.page.pageSize=valthis.loadTableData()}},/***当前面号调整事件*@paramval*/handlePageCurrentChange(val){if(val!=this.BaseTableData.page.currentPage){this.BaseTableData.page.currentPage=valthis.loadTableData()}},dialogResize(dialogName,toMax){VFC_dialogResize(dialogName,toMax)},resizeInputBaseInfoDialogMax(){this.InputBaseInfoDialogData.dialogFullScreen=true},resizeInputBaseInfoDialogNormal(){this.InputBaseInfoDialogData.dialogFullScreen=false},dialogClose(dialogName){},closeInputBaseInfoDialog(){this.InputBaseInfoDialogData.dialogVisible=falsethis.loadTableData()},asyncgetBlankForm(){constresponse=awaitgetBlankJob()if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}const{data}=responsethis.InputBaseInfoDialogData.data=data},asyncgetUpdateForm(row){constresponse=awaitgetUpdateObject(row)if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}const{data}=responsethis.InputBaseInfoDialogData.data=data},//弹出对话框handleadd(){this.getBlankForm()this.InputBaseInfoDialogData.dialogVisible=true},handleUpdate(row){if(row.triggerState!=='PAUSED'){this.$message({message:'请先挂起任务,再修改。',type:'warning'})return}this.getUpdateForm(row)this.InputBaseInfoDialogData.dialogVisible=true},search(){this.loadTableData()},/***提交修改主表单*/asyncsaveInputBaseInfoForm(){if(this.ServiceRunning){this.$message({message:'请不要重复点击。',type:'warning'})return}this.ServiceRunning=trueconstresponse=awaitsaveJob(this.InputBaseInfoDialogData.data)if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}this.ServiceRunning=falsethis.$message({message:'数据保存成功。',type:'success'})this.loadTableData()},asynchandlePause(row){if(this.ServiceRunning){this.$message({message:'请不要重复点击。',type:'warning'})return}this.ServiceRunning=trueconstresponse=awaitpauseJob(row)if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}this.ServiceRunning=falsethis.$message({message:'任务成功挂起。',type:'success'})this.loadTableData()},asynchandleResume(row){if(this.ServiceRunning){this.$message({message:'请不要重复点击。',type:'warning'})return}this.ServiceRunning=trueconstresponse=awaitresumeJob(row)if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}this.ServiceRunning=falsethis.$message({message:'任务成功恢复。',type:'success'})this.loadTableData()},asynchandleDelete(row){if(row.triggerState!=='PAUSED'){this.$message({message:'请先挂起任务,再删除。',type:'warning'})return}if(this.ServiceRunning){this.$message({message:'请不要重复点击。',type:'warning'})return}this.ServiceRunning=trueconstresponse=awaitdeleteJob(row)if(response.code!==100){this.ServiceRunning=falsethis.$message({message:response.message,type:'warning'})return}this.ServiceRunning=falsethis.$message({message:'任务成功删除。',type:'success'})this.loadTableData()},indexMethod(index){returnthis.BaseTableData.page.pageSize*(this.BaseTableData.page.currentPage-1)+index+1},dateTimeColFormatter(row,column,cellValue){returnthis.monUtils.dateTimeFormat(cellValue)},}}</script><style></style>

api定义

job.js定义访问后台接口的方式

importrequestfrom'@/utils/request'//获取空任务exportfunctiongetBlankJob(){returnrequest({url:'/api/system/auth/job/blank',method:'get'})}//获取任务列表(分页)exportfunctionfetchJobPage(data){returnrequest({url:'/api/system/auth/job/page',method:'post',data})}//获取用于修改的任务信息exportfunctiongetUpdateObject(data){returnrequest({url:'/api/system/auth/job/dataforupdate',method:'post',data})}//保存任务exportfunctionsaveJob(data){returnrequest({url:'/api/system/auth/job/save',method:'post',data})}//暂停任务exportfunctionpauseJob(data){returnrequest({url:'/api/system/auth/job/pause',method:'post',data})}//恢复任务exportfunctionresumeJob(data){returnrequest({url:'/api/system/auth/job/resume',method:'post',data})}//删除任务exportfunctiondeleteJob(data){returnrequest({url:'/api/system/auth/job/delete',method:'post',data})}

后端整合配置类单独数据源配置

Quartz会自动创建11张数据表,数据源可以与系统主数据源相同,也可以独立设置。

笔者建议单独设置Quartz数据源。在配置文件 application.yml 添加以下内容

base2048:job:enable:truedatasource:driver-class-name:&nbsp.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/base2048job?useSSL=false&serverTimezone=UTC&autoReconnect=true&allowPublicKeyRetrieval=true&useOldAliasMetadataBehavior=trueusername:rootpassword:mysql

数据源配置类如下:

@ConfigurationpublicclassQuartzDataSourceConfig{@Primary@Bean(name="defaultDataSource")@ConfigurationProperties(prefix="spring.datasource")publicDruidDataSourcedruidDataSource(){returnnewDruidDataSource();}@Bean(name="quartzDataSource")@QuartzDataSource@ConfigurationProperties(prefix="base2048.job.datasource")publicDruidDataSourcequartzDataSource(){returnnewDruidDataSource();}}

调度器配置

在 resources 下添加 quartz.properties 文件,内容如下:

#固定前缀org.quartz#主要分为scheduler、threadPool、jobStore、plugin等部分##org.quartz.scheduler.instanceName=DefaultQuartzSchedulerorg.quartz.scheduler.rmi.export=falseorg.quartz.scheduler.rmi.proxy=falseorg.quartz.scheduler.wrapJobExecutionInUserTransaction=false<!--每个集群节点要有独立的instanceId-->org.quartz.scheduler.instanceId='AUTO'#实例化ThreadPool时,使用的线程类为SimpleThreadPoolorg.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool#threadCount和threadPriority将以setter的形式注入ThreadPool实例#并发个数org.quartz.threadPool.threadCount=15#优先级org.quartz.threadPool.threadPriority=5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=trueorg.quartz.jobStore.misfireThreshold=5000#默认存储在内存中#org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore#持久化org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.tablePrefix=QRTZ_org.quartz.jobStore.dataSource=qzDSorg.quartz.dataSource.qzDS.maxConnections=10

调度器配置类内容如下:

@ConfigurationpublicclassSchedulerConfig{@AutowiredprivateMyJobFactorymyJobFactory;@Value("${base2048.job.enable:false}")privateBooleanJOB_LOCAL_RUNING;@Value("${base2048.job.datasource.driver-class-name}")privateStringdsDriver;@Value("${base2048.job.datasource.url}")privateStringdsUrl;@Value("${base2048.job.datasource.username}")privateStringdsUser;@Value("${base2048.job.datasource.password}")privateStringdsPassword;@BeanpublicSchedulerFactoryBeanschedulerFactoryBean()throwsIOException{SchedulerFactoryBeanfactory=newSchedulerFactoryBean();factory.setOverwriteExistingJobs(true);//延时启动factory.setStartupDelay(20);//用于quartz集群,QuartzScheduler启动时更新己存在的Job//factory.setOverwriteExistingJobs(true);//加载quartz数据源配置factory.setQuartzProperties(quartzProperties());//自定义JobFactory,用于Spring注入factory.setJobFactory(myJobFactory);//.neusoft.jn.gpbase.quartz.job.BaseJobTemplate同样出现该配置//原因:qrtz在集群模式下存在同一个任务一个在A服务器任务被分配出去另一个B服务器任务不再分配的情况.//if(!JOB_LOCAL_RUNING){//设置调度器自动运行factory.setAutoStartup(false);}returnfactory;}@BeanpublicPropertiesquartzProperties()throwsIOException{PropertiesFactoryBeanpropertiesFactoryBean=newPropertiesFactoryBean();propertiesFactoryBean.setLocation(newClassPathResource("/quartz.properties"));propertiesFactoryBean.afterPropertiesSet();Propertiesproperties=propertiesFactoryBean.getObject();properties.setProperty("org.quartz.dataSource.qzDS.driver",dsDriver);properties.setProperty("org.quartz.dataSource.qzDS.URL",dsUrl);properties.setProperty("org.quartz.dataSource.qzDS.user",dsUser);properties.setProperty("org.quartz.dataSource.qzDS.password",dsPassword);returnproperties;}/**通过SchedulerFactoryBean获取Scheduler的实例*/@Bean(name="scheduler")publicSchedulerscheduler()throwsException{returnschedulerFactoryBean().getScheduler();}}

任务模板

Job基类

publicabstractclassBaseJobimplementsJob,Serializable{privatestaticfinalStringJOB_MAP_KEY="self";publicstaticfinalStringSTATUS_RUNNING="1";publicstaticfinalStringSTATUS_NOT_RUNNING="0";publicstaticfinalStringCONCURRENT_IS="1";publicstaticfinalStringCONCURRENT_NOT="0";/***任务名称*/privateStringjobName;/***任务分组*/privateStringjobGroup;/***任务状态是否启动任务*/privateStringjobStatus;/***cron表达式*/privateStringcronExpression;/***描述*/privateStringdescription;/***任务执行时调用哪个类的方法包名+类名*/privateClassbeanClass=this.getClass();/***任务是否有状态*/privateStringisConcurrent;/***Springbean*/privateStringspringBean;/***任务调用的方法名*/privateStringmethodName;/***为了将执行后的任务持久化到数据库中*/@JsonIgnoreprivateJobDataMapdataMap=newJobDataMap();publicJobKeygetJobKey(){returnJobKey.jobKey(jobName,jobGroup);//任务名称和组构成任务key}publicJobDataMapgetDataMap(){if(dataMap.size()==0){dataMap.put(JOB_MAP_KEY,this);}returndataMap;}publicStringgetJobName(){returnjobName;}publicvoidsetJobName(StringjobName){this.jobName=jobName;}publicStringgetJobGroup(){returnjobGroup;}publicvoidsetJobGroup(StringjobGroup){this.jobGroup=jobGroup;}publicStringgetJobStatus(){returnjobStatus;}publicvoidsetJobStatus(StringjobStatus){this.jobStatus=jobStatus;}publicStringgetCronExpression(){returncronExpression;}publicvoidsetCronExpression(StringcronExpression){this.cronExpression=cronExpression;}publicStringgetDescription(){returndescription;}publicvoidsetDescription(Stringdescription){this.description=description;}publicClassgetBeanClass(){returnbeanClass;}publicvoidsetBeanClass(ClassbeanClass){this.beanClass=beanClass;}publicStringgetIsConcurrent(){returnisConcurrent;}publicvoidsetIsConcurrent(StringisConcurrent){this.isConcurrent=isConcurrent;}publicStringgetSpringBean(){returnspringBean;}publicvoidsetSpringBean(StringspringBean){this.springBean=springBean;}publicStringgetMethodName(){returnmethodName;}publicvoidsetMethodName(StringmethodName){this.methodName=methodName;}}

Job模板类

@Slf4jpublicabstractclassBaseJobTemplateextendsBaseJob{@Value("${base2048.job.enable:false}")privateBooleanJOB_LOCAL_RUNING;@Overridepublicfinalvoidexecute(JobExecutionContextjobExecutionContext)throwsJobExecutionException{if(JOB_LOCAL_RUNING){try{this.runing(jobExecutionContext);}catch(Exceptionex){thrownewJobExecutionException(ex);}}else{log.info("配置参数不允许在本机执行定时任务");}}publicabstractvoidruning(JobExecutionContextjobExecutionContext);}

Job示例类

业务Job从模板类继承。

@Slf4jponent@DisallowConcurrentExecutionpublicclassTestJobextendsBaseJobTemplate{@Overridepublicvoidruning(JobExecutionContextjobExecutionContext){try{log.info("测试任务开始:【{}】",Instant.now().atOffset(ZoneOffset.ofHours(8)));System.out.println("=============测试任务正在运行=====================");System.out.println("=============Testjobisrunning===============");log.info("测试任务结束:【{}】",Instant.now().atOffset(ZoneOffset.ofHours(8)));}catch(Exceptionex){log.error("测试任务异常:【{}】",Instant.now().atOffset(ZoneOffset.ofHours(8)));log.error(ex.getMessage(),ex);}}}

管理功能

Controller

@RestController@RequestMapping("/api/system/auth/job")@Slf4jpublicclassQuartzJobController{@ResourceprivateQuartzServicequartzService;@PostMapping("/save")@ApiOperation(value="保存添加或修改任务",notes="保存添加或修改任务")publicResultDTOaddOrUpdate(@RequestBodyJobUpdateDTOjobUpdateDTO)throwsException{if(StringUtils.isBlank(jobUpdateDTO.getOldJobName())){ResultDTOresultDTO=this.addSave(jobUpdateDTO);returnresultDTO;}else{/***先删除后添加*/JobDTOjobDTO=newJobDTO();jobDTO.setJobName(jobUpdateDTO.getOldJobName());jobDTO.setJobGroup(jobUpdateDTO.getOldJobGroup());this.delete(jobDTO);ResultDTOresultDTO=this.addSave(jobUpdateDTO);returnresultDTO;}}privateResultDTOaddSave(@RequestBodyJobUpdateDTOjobUpdateDTO)throwsException{BaseJobjob=(BaseJob)Class.forName(jobUpdateDTO.getJobClassName()).newInstance();job.setJobName(jobUpdateDTO.getJobName());job.setJobGroup(jobUpdateDTO.getJobGroup());job.setDescription(jobUpdateDTO.getDescription());job.setCronExpression(jobUpdateDTO.getCronExpression());try{quartzService.addJob(job);returnResultDTO.success();}catch(Exceptionex){log.error(ex.getMessage(),ex);returnResultDTO.failureCustom("保存添加任务时服务发生意外情况。");}}@PostMapping("/page")@ApiOperation(value="查询任务",notes="查询任务")publicResultDTOgetJobPage(@RequestBodyBasePageQueryVObasePageQueryVO){try{IPage<JobDTO>jobDtoPage=quartzService.queryJob(basePageQueryVO.getCurrentPage(),basePageQueryVO.getPageSize());returnResultDTO.success(jobDtoPage);}catch(Exceptionex){log.error(ex.getMessage(),ex);returnResultDTO.failureCustom("查询任务时服务发生意外情况。");}}@PostMapping("/pause")@ApiOperation(value="暂停任务",notes="暂停任务")publicResultDTOpause(@RequestBodyJobDTOjobDTO){try{quartzService.pauseJob(jobDTO.getJobName(),jobDTO.getJobGroup());returnResultDTO.success();}catch(Exceptionex){log.error(ex.getMessage(),ex);returnResultDTO.failureCustom("暂停任务时服务发生意外情况。");}}@PostMapping("/resume")@ApiOperation(value="恢复任务",notes="恢复任务")publicResultDTOresume(@RequestBodyJobDTOjobDTO){try{quartzService.resumeJob(jobDTO.getJobName(),jobDTO.getJobGroup());returnResultDTO.success();}catch(Exceptionex){log.error(ex.getMessage(),ex);returnResultDTO.failureCustom("恢复任务时服务发生意外情况。");}}@PostMapping("/delete")@ApiOperation(value="删除任务",notes="删除任务")publicResultDTOdelete(@RequestBodyJobDTOjobDTO){try{if(quartzService.deleteJob(jobDTO.getJobName(),jobDTO.getJobGroup())){returnResultDTO.failureCustom("删除失败。");}else{returnResultDTO.success();}}catch(Exceptionex){log.error(ex.getMessage(),ex);returnResultDTO.failureCustom("删除任务时服务发生意外情况。");}}@GetMapping("/blank")publicResultDTOgetBlankJobDTO(){JobUpdateDTOjobUpdateDTO=newJobUpdateDTO();jobUpdateDTO.setJobClassName(&quot.qiyuan.base2048.quartz.job.jobs.");jobUpdateDTO.setCronExpression("*/9****?");returnResultDTO.success(jobUpdateDTO);}@PostMapping("/dataforupdate")publicResultDTOgetUpdateJobDTO(@RequestBodyJobDTOjobDTO){JobUpdateDTOjobUpdateDTO=JobDtoTransMapper.INSTANCE.map(jobDTO);jobUpdateDTO.setOldJobName(jobDTO.getJobName());jobUpdateDTO.setOldJobGroup(jobDTO.getJobGroup());returnResultDTO.success(jobUpdateDTO);}}

JobDTO

@DatapublicclassJobDTO{privateStringjobClassName;privateStringjobName;privateStringjobGroup;privateStringdescription;privateStringcronExpression;privateStringtriggerName;privateStringtriggerGroup;privateStringtimeZoneId;privateStringtriggerState;privateDatestartTime;privateDatenextFireTime;privateDatepreviousFireTime;}

JobUpdateDTO

@DatapublicclassJobUpdateDTOextendsJobDTO{privateStringoldJobName;privateStringoldJobGroup;}

Service

@Service@Slf4jpublicclassQuartzServiceImplimplementsQuartzService{/***Scheduler代表一个调度容器,一个调度容器可以注册多个JobDetail和Trigger.当Trigger和JobDetail组合,就可以被Scheduler容器调度了*/@AutowiredprivateSchedulerscheduler;@ResourceprivateQrtzJobDetailsMapperqrtzJobDetailsMapper;@AutowiredprivateSchedulerFactoryBeanschedulerFactoryBean;@AutowiredpublicQuartzServiceImpl(Schedulerscheduler){this.scheduler=scheduler;}@OverridepublicIPage<JobDTO>queryJob(intpageNum,intpageSize)throwsException{List<JobDTO>jobList=null;try{Schedulerscheduler=schedulerFactoryBean.getScheduler();GroupMatcher<JobKey>matcher=GroupMatcher.anyJobGroup();Set<JobKey>jobKeys=scheduler.getJobKeys(matcher);jobList=newArrayList<>();for(JobKeyjobKey:jobKeys){List<?extendsTrigger>triggers=scheduler.getTriggersOfJob(jobKey);for(Triggertrigger:triggers){JobDTOjobDetails=newJobDTO();if(triggerinstanceofCronTrigger){CronTriggercronTrigger=(CronTrigger)trigger;jobDetails.setCronExpression(cronTrigger.getCronExpression());jobDetails.setTimeZoneId(cronTrigger.getTimeZone().getDisplayName());}jobDetails.setTriggerGroup(trigger.getKey().getName());jobDetails.setTriggerName(trigger.getKey().getGroup());jobDetails.setJobGroup(jobKey.getGroup());jobDetails.setJobName(jobKey.getName());jobDetails.setStartTime(trigger.getStartTime());jobDetails.setJobClassName(scheduler.getJobDetail(jobKey).getJobClass().getName());jobDetails.setNextFireTime(trigger.getNextFireTime());jobDetails.setPreviousFireTime(trigger.getPreviousFireTime());jobDetails.setTriggerState(scheduler.getTriggerState(trigger.getKey()).name());jobList.add(jobDetails);}}}catch(SchedulerExceptione){e.printStackTrace();}IPage<JobDTO>jobDTOPage=newPage<>(pageNum,pageSize);jobDTOPage.setRecords(jobList);jobDTOPage.setTotal(jobList.size());jobDTOPage.setCurrent(1);jobDTOPage.setPages(1);jobDTOPage.setSize(jobList.size());returnjobDTOPage;}/***添加一个任务*@paramjob*@throwsSchedulerException*/@OverridepublicvoidaddJob(BaseJobjob)throwsSchedulerException{/**创建JobDetail实例,绑定Job实现类*JobDetail表示一个具体的可执行的调度程序,job是这个可执行调度程序所要执行的内容*另外JobDetail还包含了这个任务调度的方案和策略**///指明job的名称,所在组的名称,以及绑定job类JobDetailjobDetail=JobBuilder.newJob(job.getBeanClass()).withIdentity(job.getJobKey()).withDescription(job.getDescription()).usingJobData(job.getDataMap()).build();/***Trigger代表一个调度参数的配置,什么时候去调度*///定义调度触发规则,使用cronTrigger规则Triggertrigger=TriggerBuilder.newTrigger().withIdentity(job.getJobName(),job.getJobGroup()).withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).startNow().build();//将任务和触发器注册到任务调度中去scheduler.scheduleJob(jobDetail,trigger);//判断调度器是否启动if(!scheduler.isStarted()){scheduler.start();}log.info(String.format("定时任务:%s.%s-已添加到调度器!",job.getJobGroup(),job.getJobName()));}/***根据任务名和任务组名来暂停一个任务*@paramjobName*@paramjobGroupName*@throwsSchedulerException*/@OverridepublicvoidpauseJob(StringjobName,StringjobGroupName)throwsSchedulerException{scheduler.pauseJob(JobKey.jobKey(jobName,jobGroupName));}/***根据任务名和任务组名来恢复一个任务*@paramjobName*@paramjobGroupName*@throwsSchedulerException*/@OverridepublicvoidresumeJob(StringjobName,StringjobGroupName)throwsSchedulerException{scheduler.resumeJob(JobKey.jobKey(jobName,jobGroupName));}publicvoidrescheduleJob(StringjobName,StringjobGroupName,StringcronExpression,Stringdescription)throwsSchedulerException{TriggerKeytriggerKey=TriggerKey.triggerKey(jobName,jobGroupName);//表达式调度构建器CronScheduleBuilderscheduleBuilder=CronScheduleBuilder.cronSchedule(cronExpression);CronTriggertrigger=(CronTrigger)scheduler.getTrigger(triggerKey);//按新的cronExpression表达式重新构建triggertrigger=trigger.getTriggerBuilder().withIdentity(triggerKey).withDescription(description).withSchedule(scheduleBuilder).build();//按新的trigger重新设置job执行scheduler.rescheduleJob(triggerKey,trigger);}/***根据任务名和任务组名来删除一个任务*@paramjobName*@paramjobGroupName*@throwsSchedulerException*/@OverridepublicbooleandeleteJob(StringjobName,StringjobGroupName)throwsSchedulerException{TriggerKeytriggerKey=TriggerKey.triggerKey(jobName,jobGroupName);scheduler.pauseTrigger(triggerKey);//先暂停scheduler.unscheduleJob(triggerKey);//取消调度booleanflag=scheduler.deleteJob(JobKey.jobKey(jobName,jobGroupName));returnflag;}privateJobDTOcreateJob(StringjobName,StringjobGroup,Schedulerscheduler,Triggertrigger)throwsSchedulerException{JobDTOjob=newJobDTO();job.setJobName(jobName);job.setJobGroup(jobGroup);job.setDescription("触发器:"+trigger.getKey());Trigger.TriggerStatetriggerState=scheduler.getTriggerState(trigger.getKey());job.setTriggerState(triggerState.name());if(triggerinstanceofCronTrigger){CronTriggercronTrigger=(CronTrigger)trigger;StringcronExpression=cronTrigger.getCronExpression();job.setCronExpression(cronExpression);}returnjob;}}

关于“Springboot-admin怎么整合Quartz实现动态管理定时任务”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注主机评测网行业资讯频道,小编每天都会为大家更新不同的知识点。


上一篇:Dart?String字符串的常用方法有哪些

下一篇:python怎么每天在指定时间段运行程序及关闭程序


Copyright © 2002-2019 测速网 www.inhv.cn 皖ICP备2023010105号
测速城市 测速地区 测速街道 网速测试城市 网速测试地区 网速测试街道
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!

热门搜索 城市网站建设 地区网站制作 街道网页设计 大写数字 热点城市 热点地区 热点街道 热点时间 房贷计算器