SpringBoot中使用Quartz管理定时任务的方法
定时任务在系统中用到的地方很多,例如每晚凌晨的数据备份,每小时获取第三方平台的Token信息等等,之前我们都是在项目中规定这个定时任务什么时候启动,到时间了便会自己启动,那么我们想要停止这个定时任务的时候,就需要去改动代码,还得启停服务器,这是非常不友好的事情
直至遇见Quartz,利用图形界面可视化管理定时任务,使得我们对定时任务的管理更加方便,快捷
一、Quartz简介
Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,集群,插件,EJB作业预构建,JavaMail及其它,支持cron-like表达式等等。
二、开发前戏
1、引入maven依赖
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-quartz
这里引入了web的依赖,以及Quartz的依赖,其余依赖请根据需求自行引入
2、创建数据表
数据模型:
SQL语句:
droptableifexistssys_quartz; /*==============================================================*/ /*Table:sys_quartz*/ /*==============================================================*/ createtablesys_quartz ( idbigint(20)notnullauto_incrementcomment'主键id', class_namevarchar(32)comment'任务类名', cron_expressionvarchar(32)comment'cron表达式', paramvarchar(32)comment'参数', descriptvarchar(11)comment'描述', quartz_statusvarchar(255)comment'启动状态(0--启动1--停止)', create_timedatetimecomment'创建时间', create_userbigint(20)comment'创建人', statustinyint(1)default0comment'状态(0--正常1--停用)', del_flagtinyint(1)default0comment'删除状态(0,正常,1已删除)', primarykey(id) ) type=InnoDB; altertablesys_quartzcomment'定时任务信息表';
三、开发进行中
1、创建实体类
importcom.baomidou.mybatisplus.annotation.*; importcom.baomidou.mybatisplus.extension.activerecord.Model; importcom.zyxx.common.annotation.Dict; importio.swagger.annotations.ApiModel; importio.swagger.annotations.ApiModelProperty; importlombok.Data; importlombok.EqualsAndHashCode; importlombok.experimental.Accessors; importjava.io.Serializable; /** **定时任务信息表 *
* *@authorlizhou *@since2020-07-21 */ @Data @EqualsAndHashCode(callSuper=false) @Accessors(chain=true) @TableName("sys_quartz") @ApiModel(value="SysQuartz对象",description="定时任务信息表") publicclassSysQuartzextendsModel{ @ApiModelProperty(value="主键id") @TableId(value="id",type=IdType.AUTO) privateLongid; @ApiModelProperty(value="任务类名") @TableField("class_name") privateStringclassName; @ApiModelProperty(value="cron表达式") @TableField("cron_expression") privateStringcronExpression; @ApiModelProperty(value="参数") @TableField("param") privateStringparam; @ApiModelProperty(value="描述") @TableField("descript") privateStringdescript; @ApiModelProperty(value="启动状态(0--启动1--停止)") @TableField("quartz_status") privateIntegerquartzStatus; @ApiModelProperty(value="状态(0--正常1--停用)") @TableField("status") privateIntegerstatus; @ApiModelProperty(value="删除状态(0--未删除1--已删除)") @TableField("del_flag") @TableLogic privateIntegerdelFlag; @ApiModelProperty(value="创建者") @TableField("create_user") privateLongcreateUser; @ApiModelProperty(value="创建时间") @TableField("create_time") privateStringcreateTime; @Override protectedSerializablepkVal(){ returnthis.id; } }
2、实现定时任务的CRUD
下面我们就要完成定时任务的新增、修改、删除、启停等基本操作了,由于不是很复杂,这里的代码就不贴出来了,贴几张图吧
列表页:
新增页:
四、定时任务
1、定时任务类
我们把定时任务都放在job包下面,一个定时任务就是一个文件,写一个测试的类TestJob.java
importcom.zyxx.common.utils.DateUtils; importlombok.extern.slf4j.Slf4j; importorg.quartz.Job; importorg.quartz.JobExecutionContext; importorg.quartz.JobExecutionException; /** *@ClassNameTestJob *测试定时任务 *@AuthorLizhou *@Date2020-07-2110:58:58 **/ @Slf4j publicclassTestJobimplementsJob{ @Override publicvoidexecute(JobExecutionContextjobExecutionContext)throwsJobExecutionException{ System.out.println("定时任务启动:"+DateUtils.getYmdHms()); } }
TestJob这个类实现了Job接口,实现了execute方法,这里还可以接收参数
这个文件在com.zyxx.sbm.job包下面,那么在页面新增定时任务的时候,就需要填写任务类名为:com.zyxx.sbm.job.TestJob
cron表达式的知识这里就不一一介绍了
2、页面添加定时任务
那么我们的任务类名就是:com.zyxx.sbm.job.TestJob
cron表达式:*/2****?,表示两秒钟执行一次
参数:我们没有传入参数
3、后台添加定时任务
packagecom.zyxx.sbm.service.impl; importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper; importcom.baomidou.mybatisplus.core.metadata.IPage; importcom.baomidou.mybatisplus.extension.plugins.pagination.Page; importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl; importcom.zyxx.common.shiro.SingletonLoginUtils; importcom.zyxx.common.utils.DateUtils; importcom.zyxx.common.utils.LayTableResult; importcom.zyxx.common.utils.ResponseResult; importcom.zyxx.sbm.entity.SysQuartz; importcom.zyxx.sbm.mapper.SysQuartzMapper; importcom.zyxx.sbm.service.SysQuartzService; importlombok.extern.slf4j.Slf4j; importorg.apache.commons.lang3.StringUtils; importorg.quartz.*; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Service; importjava.util.List; /** **定时任务信息表服务实现类 *
* *@authorlizhou *@since2020-07-21 */ @Slf4j @Service publicclassSysQuartzServiceImplextendsServiceImplimplementsSysQuartzService{ @Autowired privateSchedulerscheduler; /** *添加定时任务 */ @Override publicResponseResultadd(SysQuartzsysQuartz){ QueryWrapper queryWrapper=newQueryWrapper<>(); queryWrapper.eq("class_name",sysQuartz.getClassName()); List sysQuartzList=list(queryWrapper); if(null!=sysQuartzList&&!sysQuartzList.isEmpty()){ returnResponseResult.getInstance().error("该任务类名已经存在"); } sysQuartz.setCreateTime(DateUtils.getYmdHms()); sysQuartz.setCreateUser(SingletonLoginUtils.getUserId()); save(sysQuartz); //启动 if(0==sysQuartz.getQuartzStatus()){ this.schedulerAdd(sysQuartz.getClassName().trim(),sysQuartz.getCronExpression().trim(),sysQuartz.getParam()); } returnResponseResult.getInstance().success(); } /** *添加定时任务 * *@paramclassName *@paramcronExpression *@paramparam */ @Override publicvoidschedulerAdd(StringclassName,StringcronExpression,Stringparam){ try{ //启动调度器 scheduler.start(); //构建job信息 JobDetailjobDetail=JobBuilder.newJob(getClass(className).getClass()).withIdentity(className).usingJobData("param",param).build(); //表达式调度构建器(即任务执行的时间) CronScheduleBuilderscheduleBuilder=CronScheduleBuilder.cronSchedule(cronExpression); //按新的cronExpression表达式构建一个新的trigger CronTriggertrigger=TriggerBuilder.newTrigger().withIdentity(className).withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail,trigger); }catch(SchedulerExceptione){ log.error(e.getMessage()); }catch(RuntimeExceptione){ log.error(e.getMessage()); }catch(Exceptione){ log.error(e.getMessage()); } } /** *删除定时任务 * *@paramclassName */ @Override publicvoidschedulerDelete(StringclassName){ try{ scheduler.pauseTrigger(TriggerKey.triggerKey(className)); scheduler.unscheduleJob(TriggerKey.triggerKey(className)); scheduler.deleteJob(JobKey.jobKey(className)); }catch(Exceptione){ log.error(e.getMessage(),e); } } privatestaticJobgetClass(StringclassName)throwsException{ Class>class1=Class.forName(className); return(Job)class1.newInstance(); } }
需要注入Scheduler对象,使用该对象开启或停止定时任务
在启动定时任务之前,我们应先删除该任务类名开启的定时任务,防止该任务类名已经添加过了
//删除定时任务 schedulerDelete(sysQuartz.getClassName().trim()); //添加定时任务 schedulerAdd(sysQuartz.getClassName().trim(),sysQuartz.getCronExpression().trim(),sysQuartz.getParam());
添加定时任务,传入任务类名,cron表达式,参数
停止定时任务,只需要:
scheduler.pauseJob(JobKey.jobKey(sysQuartz.getClassName().trim()));
根据任务类名,停止定时任务即可
五、开发测试
启动项目,在管理界面,开启定时任务,即可在控制台看到打印的信息
表示我们的定时任务已经启动成功了
六、优化建议
当我们添加了定时任务并启动后,重新启动项目的时候,定时任务却不会自动启动,这时候,我们就需要在项目启动的时候做一些事情了,也就是系统启动任务
不清楚的同学可以复习一下之前我的博客【SpringBoot】十九、SpringBoot中实现启动任务
importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper; importcom.zyxx.sbm.entity.SysQuartz; importcom.zyxx.sbm.service.SysQuartzService; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.boot.CommandLineRunner; importorg.springframework.core.annotation.Order; importorg.springframework.stereotype.Component; importjava.util.List; /** *@ClassNameSystemStartTask *项目启动任务--启动定时任务 *@AuthorLizhou *@Date2020-07-2112:56:56 **/ @Component @Order(100) publicclassSystemQuartzStartTaskimplementsCommandLineRunner{ @Autowired privateSysQuartzServicesysQuartzService; @Override publicvoidrun(String...args)throwsException{ //查询启动的定时任务 QueryWrapperqueryWrapper=newQueryWrapper<>(); queryWrapper.eq("status",0); queryWrapper.eq("quartz_status",0); List list=sysQuartzService.list(queryWrapper); if(null!=list&&!list.isEmpty()){ for(SysQuartzitem:list){ //删除定时任务 sysQuartzService.schedulerDelete(item.getClassName().trim()); //添加定时任务 sysQuartzService.schedulerAdd(item.getClassName().trim(),item.getCronExpression().trim(),item.getParam()); } } } }
从数据库查询出启动的定时任务,并将他们添加到定时任务启动中,这样项目一启动时,就会自动启动我们定义的定时任务了
最后
任务类名的正则表达式
/^[a-zA-Z]+(\.([a-zA-Z])+)+$/
cron表达式的验证使用正则太麻烦,可以使用Quartz自带验证方法
CronExpression.isValidExpression(cron)
SpringBoot中使用Quartz管理定时任务的学习就到这儿了,其实也并不难理解,相比于之前用的定时任务是不是好很多了呢,别忘了最后加上系统启动任务哦
总结
到此这篇关于SpringBoot中使用Quartz管理定时任务的文章就介绍到这了,更多相关SpringBoot管理定时任务内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。