Spring Boot 中实现定时任务的两种方式!

在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具备这两个 Spring 中的定时任务实现策略,当然也支持 Quartz,本文我们就来看下 Spring Boot 中两种定时任务的实现方式。

@Scheduled

使用 @Scheduled 非常容易,直接创建一个 Spring Boot 项目,并且添加 web 依赖 spring-boot-starter-web,项目创建成功后,添加 @EnableScheduling 注解,开启定时任务:

  
  
  
  1. @SpringBootApplication

  2. @EnableScheduling

  3. public class ScheduledApplication {


  4. public static void main(String[] args) {

  5. SpringApplication.run(ScheduledApplication.class, args);

  6. }


  7. }

接下来配置定时任务:

  
  
  
  1. @Scheduled(fixedRate = 2000)

  2. public void fixedRate() {

  3. System.out.println("fixedRate>>>"+new Date());

  4. }

  5. @Scheduled(fixedDelay = 2000)

  6. public void fixedDelay() {

  7. System.out.println("fixedDelay>>>"+new Date());

  8. }

  9. @Scheduled(initialDelay = 2000,fixedDelay = 2000)

  10. public void initialDelay() {

  11. System.out.println("initialDelay>>>"+new Date());

  12. }

  1. 首先使用 @Scheduled 注解开启一个定时任务。

  2. fixedRate 表示任务执行之间的时间间隔,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。

  3. fixedDelay 表示任务执行之间的时间间隔,具体是指本次任务结束到下次任务开始之间的时间间隔。

  4. initialDelay 表示首次任务启动的延迟时间。

  5. 所有时间的单位都是毫秒。

上面这是一个基本用法,除了这几个基本属性之外,@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秒触发一次,如下:

  
  
  
  1. @Scheduled(cron = "0/5 * * * * *")

  2. public void cron() {

  3. System.out.println(new Date());

  4. }

上面介绍的是使用 @Scheduled 注解的方式来实现定时任务,接下来我们再来看看如何使用 Quartz 实现定时任务。

Quartz

一般在项目中,除非定时任务涉及到的业务实在是太简单,使用 @Scheduled 注解来解决定时任务,否则大部分情况可能都是使用 Quartz 来做定时任务。在 Spring Boot 中使用 Quartz ,只需要在创建项目时,添加 Quartz 依赖即可:

Spring Boot 中实现定时任务的两种方式!

项目创建完成后,也需要添加开启定时任务的注解:

  
  
  
  1. @SpringBootApplication

  2. @EnableScheduling

  3. public class QuartzApplication {

  4. public static void main(String[] args) {

  5. SpringApplication.run(QuartzApplication.class, args);

  6. }

  7. }

Quartz 在使用过程中,有两个关键概念,一个是JobDetail(要做的事情),另一个是触发器(什么时候做),要定义 JobDetail,需要先定义 Job,Job 的定义有两种方式:

第一种方式,直接定义一个Bean:

  
  
  
  1. @Component

  2. public class MyJob1 {

  3. public void sayHello() {

  4. System.out.println("MyJob1>>>"+new Date());

  5. }

  6. }

关于这种定义方式说两点:

  1. 首先将这个 Job 注册到 Spring 容器中。

  2. 这种定义方式有一个缺陷,就是无法传参。

第二种定义方式,则是继承 QuartzJobBean 并实现默认的方法:

  
  
  
  1. public class MyJob2 extends QuartzJobBean {

  2. HelloService helloService;

  3. public HelloService getHelloService() {

  4. return helloService;

  5. }

  6. public void setHelloService(HelloService helloService) {

  7. this.helloService = helloService;

  8. }

  9. @Override

  10. protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

  11. helloService.sayHello();

  12. }

  13. }

  14. public class HelloService {

  15. public void sayHello() {

  16. System.out.println("hello service >>>"+new Date());

  17. }

  18. }

和第1种方式相比,这种方式支持传参,任务启动时,executeInternal 方法将会被执行。

Job 有了之后,接下来创建类,配置 JobDetail 和 Trigger 触发器,如下:

  
  
  
  1. @Configuration

  2. public class QuartzConfig {

  3. @Bean

  4. MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {

  5. MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();

  6. bean.setTargetBeanName("myJob1");

  7. bean.setTargetMethod("sayHello");

  8. return bean;

  9. }

  10. @Bean

  11. JobDetailFactoryBean jobDetailFactoryBean() {

  12. JobDetailFactoryBean bean = new JobDetailFactoryBean();

  13. bean.setJobClass(MyJob2.class);

  14. JobDataMap map = new JobDataMap();

  15. map.put("helloService", helloService());

  16. bean.setJobDataMap(map);

  17. return bean;

  18. }

  19. @Bean

  20. SimpleTriggerFactoryBean simpleTriggerFactoryBean() {

  21. SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();

  22. bean.setStartTime(new Date());

  23. bean.setRepeatCount(5);

  24. bean.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());

  25. bean.setRepeatInterval(3000);

  26. return bean;

  27. }

  28. @Bean

  29. CronTriggerFactoryBean cronTrigger() {

  30. CronTriggerFactoryBean bean = new CronTriggerFactoryBean();

  31. bean.setCronExpression("0/10 * * * * ?");

  32. bean.setJobDetail(jobDetailFactoryBean().getObject());

  33. return bean;

  34. }

  35. @Bean

  36. SchedulerFactoryBean schedulerFactoryBean() {

  37. SchedulerFactoryBean bean = new SchedulerFactoryBean();

  38. bean.setTriggers(cronTrigger().getObject(), simpleTriggerFactoryBean().getObject());

  39. return bean;

  40. }

  41. @Bean

  42. HelloService helloService() {

  43. return new HelloService();

  44. }

  45. }

关于这个配置说如下几点:

  1. JobDetail 的配置有两种方式:MethodInvokingJobDetailFactoryBean 和 JobDetailFactoryBean 。

  2. 使用 MethodInvokingJobDetailFactoryBean 可以配置目标 Bean 的名字和目标方法的名字,这种方式不支持传参。

  3. 使用 JobDetailFactoryBean 可以配置 JobDetail ,任务类继承自 QuartzJobBean ,这种方式支持传参,将参数封装在 JobDataMap 中进行传递。

  4. Trigger 是指触发器,Quartz 中定义了多个触发器,这里向大家展示其中两种的用法,SimpleTrigger 和 CronTrigger 。

  5. SimpleTrigger 有点类似于前面说的 @Scheduled 的基本用法。

  6. CronTrigger 则有点类似于 @Scheduled 中 cron 表达式的用法。

Spring Boot 中实现定时任务的两种方式!

全部定义完成后,启动 Spring Boot 项目就可以看到定时任务的执行了。

总结

这里主要向大家展示了 Spring Boot 中整合两种定时任务的方法,整合成功之后,剩下的用法基本上就和在 SSM 中使用一致了,不再赘述。


Spring Boot 中实现定时任务的两种方式!
Spring Boot 中实现定时任务的两种方式!
关注牧码小子,后台回复 Java ,领取松哥为你精心准备的Java干货!
Spring Boot 中实现定时任务的两种方式!

往期文章一览

1、推荐一个技术圈子,Java技能提升就靠它了

2、Spring Cloud 教程合集

3、Redis教程

4、MongoDB教程合集

5、Git教程合集

Spring Boot 中实现定时任务的两种方式!
你点的每个在看,我都认真当成了喜欢

本文分享自微信公众号 - 江南一点雨(a_javaboy)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

版权声明:程序员胖胖胖虎阿 发表于 2022年9月1日 上午10:40。
转载请注明:Spring Boot 中实现定时任务的两种方式! | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...