在 spring + springmvc 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 spring 自带的定时任务处理器 @scheduled 注解,另一种就是使用第三方框架 quartz ,spring boot 源自 spring+springmvc ,因此天然具备这两个 spring 中的定时任务实现策略,当然也支持 quartz,本文我们就来看下 spring boot 中两种定时任务的实现方式。
@scheduled使用 @scheduled 非常容易,直接创建一个 spring boot 项目,并且添加 web 依赖 spring-boot-starter-web,项目创建成功后,添加 @enablescheduling 注解,开启定时任务:
@springbootapplication
@enablescheduling
publicclassscheduledapplication{
publicstaticvoid main(string[] args){
springapplication.run(scheduledapplication.class, args);
}
}
接下来配置定时任务:
@scheduled(fixedrate =2000)
publicvoid fixedrate(){
system.out.println(fixedrate>>>+newdate());
}
@scheduled(fixeddelay =2000)
publicvoid fixeddelay(){
system.out.println(fixeddelay>>>+newdate());
}
@scheduled(initialdelay =2000,fixeddelay =2000)
publicvoid initialdelay(){
system.out.println(initialdelay>>>+newdate());
}
首先使用 @scheduled 注解开启一个定时任务。fixedrate 表示任务执行之间的时间间隔,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。fixeddelay 表示任务执行之间的时间间隔,具体是指本次任务结束到下次任务开始之间的时间间隔。initialdelay 表示首次任务启动的延迟时间。所有时间的单位都是毫秒。上面这是一个基本用法,除了这几个基本属性之外,@scheduled 注解也支持 cron 表达式,使用 cron 表达式,可以非常丰富的描述定时任务的时间。cron 表达式格式如下:
[秒] [分] [小时] [日] [月] [周] [年]
具体取值如下:
序号说明是否必填允许填写的值允许的通配符
1 秒 是 0-59 - * /
2 分 是 0-59 - * /
3 时 是 0-23 - * /
4 日 是 1-31 - * ? / l w
5 月 是 1-12 or jan-dec - * /
6 周 是 1-7 or sun-sat - * ? / l #
7 年 否 1970-2099 - * /
这一块需要大家注意的是,月份中的日期和星期可能会起冲突,因此在配置时这两个得有一个是 ?
通配符含义:
? 表示不指定值,即不关心某个字段的取值时使用。需要注意的是,月份中的日期和星期可能会起冲突,因此在配置时这两个得有一个是 ?* 表示所有值,例如:在秒的字段上设置 *,表示每一秒都会触发, 用来分开多个值,例如在周字段上设置 mon,wed,fri 表示周一,周三和周五触发- 表示区间,例如在秒上设置 10-12,表示 10,11,12秒都会触发/ 用于递增触发,如在秒上面设置5/15 表示从5秒开始,每增15秒触发(5,20,35,50)# 序号(表示每月的第几个周几),例如在周字段上设置6#3表示在每月的第三个周六,(用 在母亲节和父亲节再合适不过了)周字段的设置,若使用英文字母是不区分大小写的 ,即 mon 与mon相同l 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会自动判断是否是润年), 在周字段上表示星期六,相当于7或sat(注意周日算是第一天)。如果在l前加上数字,则表示该数据的最后一个。例如在周字段上设置6l这样的格式,则表示本月最后一个星期五w 表示离指定日期的最近工作日(周一至周五),例如在日字段上设置15w,表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发,如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 1w,它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,w前只能设置具体的数字,不允许区间-)l 和 w 可以一组合使用。如果在日字段上设置lw,则表示在本月的最后一个工作日触发(一般指发工资 )例如,在 @scheduled 注解中来一个简单的 cron 表达式,每隔5秒触发一次,如下:
@scheduled(cron =0/5 * * * * *)
publicvoid cron(){
system.out.println(newdate());
}
上面介绍的是使用 @scheduled 注解的方式来实现定时任务,接下来我们再来看看如何使用 quartz 实现定时任务。
quartz一般在项目中,除非定时任务涉及到的业务实在是太简单,使用 @scheduled 注解来解决定时任务,否则大部分情况可能都是使用 quartz 来做定时任务。在 spring boot 中使用 quartz ,只需要在创建项目时,添加 quartz 依赖即可:
项目创建完成后,也需要添加开启定时任务的注解:
@springbootapplication
@enablescheduling
publicclassquartzapplication{
publicstaticvoid main(string[] args){
springapplication.run(quartzapplication.class, args);
}
}
quartz 在使用过程中,有两个关键概念,一个是jobdetail(要做的事情),另一个是触发器(什么时候做),要定义 jobdetail,需要先定义 job,job 的定义有两种方式:
第一种方式,直接定义一个bean:
@component
publicclassmyjob1{
publicvoid sayhello(){
system.out.println(myjob1>>>+newdate());
}
}
关于这种定义方式说两点:
首先将这个 job 注册到 spring 容器中。这种定义方式有一个缺陷,就是无法传参。第二种定义方式,则是继承 quartzjobbean 并实现默认的方法:
publicclassmyjob2extendsquartzjobbean{
helloservice helloservice;
publichelloservice gethelloservice(){
return helloservice;
}
publicvoid sethelloservice(helloservice helloservice){
this.helloservice = helloservice;
}
@override
protectedvoid executeinternal(jobexecutioncontext jobexecutioncontext)throwsjobexecutionexception{
helloservice.sayhello();
}
}
publicclasshelloservice{
publicvoid sayhello(){
system.out.println(hello service >>>+newdate());
}
}
和第1种方式相比,这种方式支持传参,任务启动时,executeinternal 方法将会被执行。
job 有了之后,接下来创建类,配置 jobdetail 和 trigger 触发器,如下:
@configuration
publicclassquartzconfig{
@bean
methodinvokingjobdetailfactorybean methodinvokingjobdetailfactorybean(){
methodinvokingjobdetailfactorybean bean =newmethodinvokingjobdetailfactorybean();
bean.settargetbeanname(myjob1);
bean.settargetmethod(sayhello);
return bean;
}
@bean
jobdetailfactorybean jobdetailfactorybean(){
jobdetailfactorybean bean =newjobdetailfactorybean();
bean.setjobclass(myjob2.class);
jobdatamap map =newjobdatamap();
map.put(helloservice, helloservice());
bean.setjobdatamap(map);
return bean;
}
@bean
simpletriggerfactorybean simpletriggerfactorybean(){
simpletriggerfactorybean bean =newsimpletriggerfactorybean();
bean.setstarttime(newdate());
bean.setrepeatcount(5);
bean.setjobdetail(methodinvokingjobdetailfactorybean().getobject());
bean.setrepeatinterval(3000);
return bean;
}
@bean
crontriggerfactorybean crontrigger(){
crontriggerfactorybean bean =newcrontriggerfactorybean();
bean.setcronexpression(0/10 * * * * ?);
bean.setjobdetail(jobdetailfactorybean().getobject());
return bean;
}
@bean
schedulerfactorybean schedulerfactorybean(){
schedulerfactorybean bean =newschedulerfactorybean();
bean.settriggers(crontrigger().getobject(), simpletriggerfactorybean().getobject());
return bean;
}
@bean
helloservice helloservice(){
returnnewhelloservice();
}
}
关于这个配置说如下几点:
jobdetail 的配置有两种方式:methodinvokingjobdetailfactorybean 和 jobdetailfactorybean 。使用 methodinvokingjobdetailfactorybean 可以配置目标 bean 的名字和目标方法的名字,这种方式不支持传参。使用 jobdetailfactorybean 可以配置 jobdetail ,任务类继承自 quartzjobbean ,这种方式支持传参,将参数封装在 jobdatamap 中进行传递。trigger 是指触发器,quartz 中定义了多个触发器,这里向大家展示其中两种的用法,simpletrigger 和 crontrigger 。simpletrigger 有点类似于前面说的 @scheduled 的基本用法。crontrigger 则有点类似于 @scheduled 中 cron 表达式的用法。
全部定义完成后,启动 spring boot 项目就可以看到定时任务的执行了。
总结这里主要向大家展示了 spring boot 中整合两种定时任务的方法,整合成功之后,剩下的用法基本上就和在 ssm 中使用一致了,不再赘述。
农兽药残留检测仪的检测项目及性能
QPA9903高效放大器
谁能说说M12连接器与普通连接器的区别
你知道造成电感值低的原因有哪些
电脑中出现一个或多个音频服务未运行的问题如何解决
Spring Boot中整合两种定时任务的方法
三星S8和华为P10将难免一战 发布前这些重磅爆料吊粉丝胃口
人工智能可能会替代人类吗
韩国着重于发展军用仿生机器人领域
5G标准的投票风波把联想推上舆论巅峰,那你们了解5G标准吗?
西门子PLC多重背景的使用规则与解决方法
如何认识电动机型号表示的名称和参数
什么是机器视觉?视觉系统组成部分
小米将在2020年第一季度推出LPDDR5手持设备
北大博士设计的无人驾驶船问世
Modbus TCP转Profinet协议网关应用
中国移动5G应用示范网在雄安新区正式开通
立体声平衡指示器电路图分享
科迈罗Track概念车亮相日内瓦 性能升级
前乐视智能驾驶负责人创办禾多科技 主攻L3.5级自动驾驶