1。前言 定时任务绝对是实际项目中的刚需。我们想监控一个重点服务的运行状态,可以每隔1分钟调用下该服务的心跳接口,调用失败时即发出告警信息;我们想每天凌晨的时候,将所有商品的库存置满,以免早上忘记添加库存影响销售;我们想在每个周六的某个时段进行打折促销。 在以上的案例中,或者是指定时间间隔,或者是指定时间节点,按设定的任务进行某种操作,这就是定时任务了。 在SpringBoot中实现定时任务简单而灵活,本节我们来体验下。2。SpringTask定时任务 SpringTask是SpringBoot内置的定时任务模块,可以满足大部分的定时任务场景需求。 通过为方法添加一个简单的注解,即可按设定的规则定时执行该方法。 下面就演示下SpringBoot中使用SpringTask的具体方法。2。1使用SpringInitializr创建项目 SpringBoot版本选择2。2。5,Group为com。imooc,Artifact为springboottask,生成项目后导入Eclipse开发环境。2。2开启定时任务 在启动类上添加EnableScheduling注解,开启定时任务功能。 实例:SpringBootApplicationEnableScheduling开启定时任务publicclassSpringBootTaskApplication{publicstaticvoidmain(String〔〕args){SpringApplication。run(SpringBootTaskApplication。class,args);}}2。3通过注解设定定时任务 新建MySpringTask任务类,添加Component注解注册Spring组件,定时任务方法需要在Spring组件类才能生效。 注意类中方法添加了Scheduled注解,所以会按照Scheduled注解参数指定的规则定时执行。 实例:任务类ComponentpublicclassMySpringTask{每2秒执行1次Scheduled(fixedRate2000)publicvoidfixedRateMethod()throwsInterruptedException{System。out。println(fixedRateMethod:newDate());Thread。sleep(1000);}} 上面例子执行情况如下,可见是每隔2秒执行1次。fixedRateMethod:FriMay1522:04:52CST2020fixedRateMethod:FriMay1522:04:54CST2020fixedRateMethod:FriMay1522:04:56CST2020 实例:任务类ComponentpublicclassMySpringTask{执行结束2秒后执行下次任务Scheduled(fixedDelay2000)publicvoidfixedDelayMethod()throwsInterruptedException{System。out。println(fixedDelayMethod:newDate());Thread。sleep(1000);}} 上面的例子执行情况如下,每次打印后先等待1秒,然后方法执行结束2秒后再次执行任务,所以是每3秒打印1行内容。fixedDelayMethod:FriMay1522:08:26CST2020fixedDelayMethod:FriMay1522:08:29CST2020fixedDelayMethod:FriMay1522:08:32CST20202。4使用Cron表达式 Scheduled也支持使用Cron表达式,Cron表达式可以非常灵活地设置定时任务的执行时间。以本节开头的两个需求为例:我们想监控一个重点服务的运行状态,可以每隔1分钟调用下该服务的心跳接口,调用失败时即发出告警信息;我们想在每天凌晨的时候,将所有商品的库存置满,以免早上忘记添加库存影响销售。 对应的定时任务实现如下: 实例:任务类ComponentpublicclassMySpringTask{在每分钟的00秒执行Scheduled(cron0?)publicvoidjump()throwsInterruptedException{System。out。println(心跳检测:newDate());}在每天的00:00:00执行Scheduled(cron000?)publicvoidstock()throwsInterruptedException{System。out。println(置满库存:newDate());}} Cron表达式并不难理解,从左到右一共6个位置,分别代表秒、时、分、日、月、星期,以秒为例:如果该位置上是0,表示在第0秒执行;如果该位置上是,表示每秒都会执行;如果该位置上是?,表示该位置的取值不影响定时任务,由于月份中的日和星期可能会发生意义冲突,所以日、星期中需要有一个配置为?。 按照上面的理解,cron0?表示在每分钟的00秒执行、cron000?表示在每天的00:00:00执行。 Tips:Cron表达式的描述能力很强,此处只是简单提及,感兴趣的同学可以自行查阅相关资料了解更多信息。3。Quartz定时任务 SpringTask已经可以满足绝大多数项目对定时任务的需求,但是在企业级应用这个领域,还有更加强大灵活的Quartz框架可供选择。 Quartz官网介绍:企业级的任务调度框架 举个例子,当我们想根据数据库中的配置,动态地指定商品打折的时间区间时,就可以利用Quartz框架来实现。OK,接下来我们就来具体完整实现下。3。1使用SpringInitializr创建项目 SpringBoot版本选择2。2。5,Group为com。imooc,Artifact为springbootquartz,生成项目后导入Eclipse开发环境。3。2引入项目依赖 需要引入Quartz框架相关依赖。 实例:!QuartzdependencygroupIdorg。springframework。bootgroupIdspringbootstarterquartzartifactIddependency3。3开启定时任务 同样需要,在启动类上添加EnableScheduling注解,开启定时任务功能。 实例:SpringBootApplicationEnableScheduling开启定时任务publicclassSpringBootQuartzApplication{publicstaticvoidmain(String〔〕args){SpringApplication。run(SpringBootQuartzApplication。class,args);}}3。4Quartz定时任务开发 Quartz定时任务需要通过Job、Trigger、JobDetail来设置。Job:具体任务操作类Trigger:触发器,设定执行任务的时间JobDetail:指定触发器执行的具体任务类及方法 我们先开发一个Job组件: 实例:打折任务Component注册到容器中publicclassDiscountJob{执行打折publicvoidexecute(){System。out。println(更新数据库中商品价格,统一打5折);}} 然后在配置类中设定Trigger及JobDetail。 实例:定时任务配置ConfigurationpublicclassQuartzConfig{配置JobDetail工厂组件,生成的JobDetail指向discountJob的execute()方法BeanMethodInvokingJobDetailFactoryBeanjobFactoryBean(){MethodInvokingJobDetailFactoryBeanbeannewMethodInvokingJobDetailFactoryBean();bean。setTargetBeanName(discountJob);bean。setTargetMethod(execute);returnbean;}触发器工厂BeanCronTriggerFactoryBeancronTrigger(){CronTriggerFactoryBeanbeannewCronTriggerFactoryBean();Corn表达式设定执行时间规则bean。setCronExpression(008?7);执行JobDetailbean。setJobDetail(jobFactoryBean()。getObject());returnbean;}} 具体分析下上面的代码:触发器设定的Corn表达式为008?7,表示每周六的08:00:00执行1次;触发器指定的JobDetail为jobFactoryBean工厂的一个对象,而jobFactoryBean指定的对象及方法为discountJob与execute();所以每周六的8点,就会运行discountJob组件的execute()方法1次;Corn表达式和执行任务、方法均以参数形式存在,这就意味着我们完全可以根据文件或数据库配置动态地调整执行时间和执行的任务;最后,周六8点的时候,商品都打了5折,别忘了促销结束的时候恢复价格啊。4。小结 SpringBoot可以利用一个简单的注解,快速实现定时任务的功能。 说实话我第一次使用Scheduled注解时,完全被这种开箱即用型的简洁震撼了,我的感受是:似乎不能更加简洁了。 如果感觉SpringTask提供的定时任务机制还不足以满足需求,SpringBoot还可以方便地集成Quartz框架来帮忙。 开箱即用满足不了,还可以即插即用,确实够人性化的。