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

这一块需要大家注意的是,月份中的日期和星期可能会起冲突,因此在配置时这两个得有一个是 ?

通配符含义:

  • ? 表示不指定值,即不关心某个字段的取值时使用。需要注意的是,月份中的日期和星期可能会起冲突,因此在配置时这两个得有一个是 ?

  • * 表示所有值,例如:在秒的字段上设置 *,表示每一秒都会触发

  • , 用来分开多个值,例如在周字段上设置 “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"前只能设置具体的数字,不允许区间”-")

  • LW 可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发(一般指发工资 )

例如,在 @Scheduled 注解中来一个简单的 cron 表达式,每隔5秒触发一次,如下:

@Scheduled(cron = “0/5 * * * * *”)

public void cron() {

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

}

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

Quartz

=================================================================

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

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

@SpringBootApplication

@EnableScheduling

public class QuartzApplication {

public static void main(String[] args) {

SpringApplication.run(QuartzApplication.class, args);

}

}

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

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

@Component

public class MyJob1 {

public void sayHello() {

System.out.println(“MyJob1>>>”+new Date());

}

}

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

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

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

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

public class MyJob2 extends QuartzJobBean {

HelloService helloService;

public HelloService getHelloService() {

return helloService;

}

public void setHelloService(HelloService helloService) {

this.helloService = helloService;

}

@Override

protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

helloService.sayHello();

}

}

public class HelloService {

public void sayHello() {

System.out.println(“hello service >>>”+new Date());

}

}

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

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

@Configuration

public class QuartzConfig {

@Bean

MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {

MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();

bean.setTargetBeanName(“myJob1”);

bean.setTargetMethod(“sayHello”);

return bean;

}

@Bean

JobDetailFactoryBean jobDetailFactoryBean() {

JobDetailFactoryBean bean = new JobDetailFactoryBean();

bean.setJobClass(MyJob2.class);

JobDataMap map = new JobDataMap();

map.put(“helloService”, helloService());

bean.setJobDataMap(map);

return bean;

}

@Bean

SimpleTriggerFactoryBean simpleTriggerFactoryBean() {

SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();

bean.setStartTime(new Date());

bean.setRepeatCount(5);

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

bean.setRepeatInterval(3000);

return bean;

}

@Bean

CronTriggerFactoryBean cronTrigger() {

CronTriggerFactoryBean bean = new CronTriggerFactoryBean();

bean.setCronExpression(“0/10 * * * * ?”);

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

return bean;

}

@Bean

SchedulerFactoryBean schedulerFactoryBean() {

SchedulerFactoryBean bean = new SchedulerFactoryBean();

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

return bean;

}

@Bean

HelloService helloService() {

return new HelloService();

}

}

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

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

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

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

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

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

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

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

写在最后

作为一名即将求职的程序员,面对一个可能跟近些年非常不同的 2019 年,你的就业机会和风口会出现在哪里?在这种新环境下,工作应该选择大厂还是小公司?已有几年工作经验的老兵,又应该如何保持和提升自身竞争力,转被动为主动?

就目前大环境来看,跳槽成功的难度比往年高很多。一个明显的感受:今年的面试,无论一面还是二面,都很考验Java程序员的技术功底。

最近我整理了一份复习用的面试题及面试高频的考点题及技术点梳理成一份“Java经典面试问题(含答案解析).pdf和一份网上搜集的“Java程序员面试笔试真题库.pdf”(实际上比预期多花了不少精力),包含分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货!

由于篇幅有限,为了方便大家观看,这里以图片的形式给大家展示部分的目录和答案截图!

Java经典面试问题(含答案解析)

阿里巴巴技术笔试心得

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

里以图片的形式给大家展示部分的目录和答案截图!**
[外链图片转存中…(img-x4s4gfcg-1712867959585)]

Java经典面试问题(含答案解析)

[外链图片转存中…(img-Vdq27D0T-1712867959586)]

阿里巴巴技术笔试心得

[外链图片转存中…(img-w69AB8Q6-1712867959586)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-skpq5T18-1712867959586)]

  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值