目录 前言 Quartz 什么是Quartz Quartz作用 Quartz结构 表达式 案例 Quartz实战 添加依赖 创建Job类 创建配置类 测试代码 扩展练习 结语 前言 在上一篇博客中,我们对单点登录有了初步了
目录
在上一篇博客中,我们对单点登录有了初步了解,这也让我们独立做系统有了最基础的保障。但在业务开发中,总是会出现一些定期处理的任务,我们首先想到的是Timer,但由于其调度功能单一,我们实际并不会用它来做项目中的任务调度。今天我们就针对定期任务来说说Quartz这个时间调度工具和它的具体用法。
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Quartz 允许程序开发人员根据时间的间隔来调度作业,它实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。听起来好可怕,功能也太强大了。但从字里行间我们还是读出来,它主要是用于延时的。
上面我们说,Quartz主要用于延时,这么说没错,也是其最本质的功能,但它还有一个强大的功能:任务调度。因为它并不是只针对某一个任务,而是针对成千上万的任务,就像一个强的控制中心,我们称之为调度。
我们知道,城市的公交地铁是有调度中心的,他们都是按照某些固定的规律来运行,比如间隔多久发一趟车,更高级的会有动态调度,这恐怕超过了我们今天要说的范畴。
之所以不使用Timer而使用Quartz,是因为Quartz有着更加便捷的时间指定方式。比如,每月1号执行一个任务,可以想想Timer要怎么做?是不是要计算每月的天数,往大了还有平年闰年,而Quartz则不用这么麻烦,两相比较,Quartz成了最好的选择。
在继续讲下去之前,我们要先知道Quartz的几个核心概念,了解了这几个组件,有助于我们更好地理解Quartz的工作原理。
void execute(JobExecutionContext context)
一般是创建一个类,继承此接口,重写内部方法来执行一些具体的任务。
看到这里,Quartz我们就了解了大半了,听起来很像移动端的通知,或者叫广播,也很像Nacos的注册服务,总之服务一定要注册才能被统一管理。你会发现,统一管理的理念就是一定要知道注册方和调用方是谁才能正常的工作,否则就全乱套了。
序号 | 时间单位 | 必填/选填 | 值范围 | 可选通配符 |
1 | 秒 | 必填 | 0~59 | ,-*/ |
2 | 分 | 必填 | 0~59 | ,-*/ |
3 | 时 | 必填 | 0~23 | ,-*/ |
4 | 日 | 必填 | 1~31 | ,-*/?LW |
5 | 月 | 必填 | 1~12/JAN~DEC | ,-*/ |
6 | 周 | 必填 | 1~7/SUN~SAT | ,-*/?L# |
7 | 年 | 选填 | empty/1970~2099 | ,-*/ |
双十一写法:0 0 0 11 11 ?
每月最后一个工作日写法:0 0 0 LW * ?
父亲节写法:0 0 0 * 6 7#3 父亲节是每年6月的第3个星期日,看看解析结果:
不确定对不对的小伙伴可以去对日历看看,哈哈。
国庆节写法:0 0 0 1 10 *
写的有点停不下来,真是太有意思了。大家可以自己写写看,从左到右要和:秒,分,时,日,月,周,年一一对应,最后一个年可以不写,如果是每年的话,你就是加个*也是可以的,因为指定具体年份貌似没有意义,一般都是当年,你不可能今年安排明年的活动,即使年底12月,预约下一年12月前的日期,也不需要写年份如果你当年11月预约下年12月的活动,那就需要写具体年份,但你不觉得这样很不礼貌吗?
反解析Cron工具地址给大家贴一个:Cron - 在线Cron表达式生成器
类似的工具还有很多,根据自己喜好选择即可。
下面,我们要在Spring Boot项目中来进行接入,就以我们前文中微服务项目为模版,新朋友没有一跟着做前面教程的话也可单独建项目来接入,并不会有什么影响。
我们选择在cloud-stock子工程下引入Quartz依赖:
org.springframework.boot spring-boot-starter-quartz
单独建项目的童鞋根据后续使用需要再自行引入其他的依赖,后续不再针对依赖引入做额外说明。
在stock子项目下创建quartz包,包下创建QuartzJob类:
以后默认子项目下创建包都是在主包下,启动文件同级别目录创建,万万不要创建在src之外。在其他包下创建会说明的,之前就出现有童鞋创建错位置的情况,作为一名Java开发工程师,这个是 不应该的。
看看这个类中的代码:
package com.codingfire.cloud.stock.quartz;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.time.LocalDateTime;public class QuartzJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { //输出当前时间 System.out.println("--------------"+ LocalDateTime.now() +"---------------"); }}
暂不做任何处置,只是重写了前面提到的 execute方法,因为Job会执行此方法,重写可以做一些其他操作,此处暂时只输出当前时间。
在quartz包下,继续创建一个QuartzConfig类,这是一个SpringBoot的配置类,也是Quartz调度器的配置类,其代码的编写格式基本是固定的,以后需要使用时可直接套用此格式,下面我们写个每10秒触发一次输出当前日期的任务:
package com.codingfire.cloud.stock.quartz;import org.quartz.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;// 这个配置类就是在配置已经保存在Spring容器中的调度器Scheduler// 我们需要按下面格式进行配置,才能让Scheduler正常工作@Configurationpublic class QuartzConfig { // 创建一个JobDetail(工作详情)类对象,保存到Spring容器中,这个类用于封装我们编写的job接口实现类 // @Bean注解标记的方法的返回值会自动保存到Spring容器中(方法名随意) @Bean public JobDetail showTime(){ System.out.println("showTime方法运行"); return JobBuilder.newJob(QuartzJob.class) // 绑定要运行的任务类的反射 .withIdentity("date") // 设置这个job的名称 .storeDurably() // .build(); } // 下面要声明触发器,Trigger,触发器决定我们的工作/任务何时触发 @Bean public Trigger showTimeTrigger(){ System.out.println("showTime触发器运行"); // 定义Cron表达式 每10秒触发一次的定义 CronScheduleBuilder cronScheduleBuilder= CronScheduleBuilder.cronSchedule("0/10 * * * * ?"); return TriggerBuilder.newTrigger() .forJob(showTime()) // 绑定JobDetail JobDetail对象已经在Spring容器中 .withIdentity("dateTrigger") // 定义触发器名称 .withSchedule(cronScheduleBuilder) // 绑定Cron表达式 .build(); }}
测试前,如果你实在微服务项目中跟着博主一起操作的,nacos和seata需要先启动,否则会报错,我们的配置文件有配置,若你是新建的项目,则不需要启动这两个服务,只需要确保你的项目能运行起来即可。
启动后,理论上每隔10s会输出一次当前系统时间,我们看看控制台有没有输出:
可以看到是每10s输出一次,你也可以在此处做一些其他的操作,都随你。
storeDurably 需要特别说明下,设置后,如果没有触发器指向此JobDetail,JobDetail也不会被从Spring容器内删除,否则,就会自动从Spring容器内删除。
其实在这个任务中,我们更希望能看到它去调用微服务其他模块的东西,这才是任务调度的真实使用场景,而不是去输出一些东西。下面,我们来尝试调用业务模块来减少库存。
在quartz包下新建一个job类:
package com.codingfire.cloud.stock.quartz;import com.codingfire.cloud.commons.pojo.stock.dto.StockReduceCountDTO;import com.codingfire.cloud.stock.service.IStockService;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.beans.factory.annotation.Autowired;public class StockJob implements Job { @Autowired private IStockService iStockService; @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { //库存-10 StockReduceCountDTO stockReduceCountDTO = new StockReduceCountDTO(); stockReduceCountDTO.setCommodityCode("PC100"); stockReduceCountDTO.setReduceCount(-10); iStockService.reduceCommodityCount(stockReduceCountDTO); }}
这就是Spring容器的好处,我们直接 @Autowired就可以拿到调用接口,我们在controller里面也是这么用的,在任务调度中也可以当作controller来用,是不是很棒。
这里可以新建一个config类,但我们选择写在输出时间的配置类里,方便大家和前面的代码做对比,添加如下代码:
@Bean public JobDetail addStock(){ return JobBuilder.newJob(StockJob.class) .withIdentity("addStock") .storeDurably() .build(); } @Bean public Trigger addStockTrigger(){ //从0开始,每1分钟运行一次 CronScheduleBuilder cronScheduleBuilder= CronScheduleBuilder.cronSchedule("0 0/1 * * * ?"); return TriggerBuilder.newTrigger() .forJob(addStock()) .withIdentity("addStockTrigger") .withSchedule(cronScheduleBuilder) .build(); }
几乎和上面的代码是一样的,只是改了一点参数。那么到这里练习就结束了,如果需要用到dubbo的,和微服务里面一样的,直接用就行,代码就不再贴了,大家可以自己试试。
赶紧关掉这些服务,博主的电脑已经吼起来了。Quart使用起来还是很简单的,也很实用,在项目中使用也很频繁,比如在csdn平台,每周都会有一周小结,都会有一些固定的服务,这些都是通过任务调度自动完成的。看到这里,你对Quart了解了吗,会用了吗?有没有自己上手?咱们下一篇内容再见。
来源地址:https://blog.csdn.net/CodingFire/article/details/129340220
--结束END--
本文标题: Java开发 - Quartz初体验
本文链接: https://lsjlt.com/news/399077.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-04-01
2024-04-03
2024-04-03
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0