SpringBoot——Quartz 定时任务

优质博文:IT-BLOG-CN

一、Scheduled 定时任务

【1】添加Scheduled相关依赖,它是Spring自带的一个jar包因此引入Spring的依赖:

<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId>
</dependency>

【2】导入依赖之后,就可以在Maven Dependencies中看到相关的依赖,如下:

【3】编写定时任务类:重点是@Scheduled注解和cron属性;

/*** Scheduled 定时任务* 定时任务不属于持久层也不属于业务层,所以应该使用 @Component 进行标记* @author Administrator**/
@Component
public class ScheduledDemo {/*** 定时任务方法,如果是定时任务方法,需要添加 scheduled注解* scheduled:表示当前方法就是一个定时任务方法* cron属性: 定时任务触发时间的一个字符串表达式* 触发条件:每2秒触发一次,博客后面重点说 cron 表达式*/@Scheduled(cron="0/2 * * * * ?")public void scheduledMethod() {System.out.println("定时任务"+new Date());}
}

【4】在启动类中开启定时任务的启动:@EnableScheduling注解

@SpringBootApplication
@EnableScheduling
public class ScheduledApplication {public static void main(String[] args) {SpringApplication.run(ScheduledApplication.class, args);}
}

【5】cron 表达式:是一个字符串,分为 6 或 7 个域(建议使用 6个域),每个域代表一个含义 :
 ■ 7个域:Seconds Minutes Hours Day Month Week Year (秒、分、小时、月份中的日期、月分、星期中的日期、年)
 ■ 6个域(少一个 Year):Seconds Minutes Hours Day Month Week

【6】各cron 字段的含义:星期和日是有冲突的,一般会舍掉一个。表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感;

位置时间域名允许值允许的特殊字符
10-59, - * /
2分钟0-59, - * /
3小时0-23, - * /
40-31, - * / ? L W C
51-12, - * /
6星期1-7, - * / ? L C #
71970-2099, - * /

①、星号(*):可用在所有字段中,表示对应时间域的每一个时刻。例如在秒时间域中表示每一秒;
②、问号(?):该字段只在星期和日期域中使用,它通常指定为“无意义的值”,相当于一个占位符;
③、减号(-):表示的是一个范围,如在小时字段中使用1-3,则表示 1,2,3点都执行;
④、逗号(,):表示一个列表值,如在秒域中使用 12,15表示第12秒和第15秒触发跑批;
⑤、斜杠(/):x/y 表示一个等步长序列,x为起始值,y为增量步长值,例如秒中使用 0/2 表示从0秒开始,没过2秒执行一次。
⑥、L:该字符只在日期和星期域中使用,但它在两个字段中的意思不同。L在日期字段表示月份的最后一天,如一月的31,二月的28等,如果在星期域中表示星期六(7),但是如果L出现在星期字段里,而且前面有一个数值 X,则表示这个月的最后 X 天,例如:6L表示该月的最后星期五;
⑦、W:该字符只能出现在日期域中,表示离该日期最近的工作日,例如 15W:表示离该月15号最近的工作日,如果15号是星期六则匹配星期五 14号。如果15号是星期日则匹配星期一 16日。如果15号是星期三则匹配星期三 15号本身。但需要注意关联的匹配不能够跨月,例如15号是2月的最后一天星期日,应该向下配置3月1日,但是不能跨月,只能匹配2月26星期五(2月最后一个工作日)W只能指定单一日期,不能指定范围;
⑧、LW组合:在日期字段组合使用,表示当月的最后一个工作日;
⑨、#号:该字符只能在星期域中使用,表示当月某个工作日。如6#3:表示当月的第三个星期五。
⑩、C:该字符只在日期和星期中使用,表示“Calendar” 的意思,表示计划所关联的日期。如果日期没有被关联,则表示所有日期。例如5C在日期域中表示 5日以后的第一天。1C在星期域中表示星期日后的第一天。

二、Springboot 整合Quartz 定时任务框架

Quartz 是 OpenSymphony开源组织在 Job scheduling(任务调度)领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz 可以用来创建简单或为运行十个,百个,甚至是好几万个 Jobs这样复杂的程序。Jobs 可以做成标准的 Java组件或 EJBs。Quartz是一个完全由 Java编写的开源作业调度框架。

【1】quartz 的 maven 依赖:

<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.2</version>
</dependency>

【2】 Job(任务:你要做什么事):

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;/***  定时任务类* @author zzx**/
public class QuartzDemo implements Job{/*** 任务触发时所执行的方法*/public void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("任务调度"+new Date());}
}

【3】Trigger(触发器:什么时候去做):有两种形式进行表达,其中一种就是 cron 表达式

【4】scheduler(任务调度:你什么时候需要做什么事):将 job 与 Trigger 进行整合。下面是一个例子:

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;public class QuartzMain {public static void main(String[] args) throws Exception {//1、Job(任务:你要做什么事),这里使用的是建造者模式JobDetail job = JobBuilder.newJob(QuartzDemo.class).build();//2、Trigger(触发器:什么时候去做),这里 triggerbuilder 也是用建造者模式封装。触发条件分为两种//3.1 第一种:简单的 trigger 触发时间,通过 Quartz 提供方法完成简单的重复调用。如下一个例子:每秒触发一次//Trigger build = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever()).build();//3.2 第二种:按照 cron 的表达式来给定触发时间Trigger trigger= TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")).build();//3、scheduler(任务调度:你什么时候需要做什么事) 将上面的job 和 trigger进行组装 这里使用工厂模式。Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();defaultScheduler.scheduleJob(job, trigger);//4、启动defaultScheduler.start();}
}

三、SpringBoot 整合 Quartz

【1】整合时相关依赖一下:

 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!--Quartz 坐标--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency><!--事务--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></dependency>
</dependencies>

【2】 创建一个 Job 类:实现 Job 接口

/***  定时任务类* @author zzx**/
public class QuartzDemo implements Job {/*** 任务触发时所执行的方法*/public void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("任务调度"+new Date());}
}

【3】编写 Quartz 的配置参数

import com.example.demo.scheduled.QuartzDemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;/*** quartz 配置类*/
@Configuration
public class QuartzConfig {//1、创建 Job 对象@Beanpublic JobDetailFactoryBean jobDetailFactoryBean(){JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();//通过反射的方式实例化 Job,并没有经过 spring 处理,所以依赖的对象不能通过 autowrite 注入jobDetailFactoryBean.setJobClass(QuartzDemo.class);return jobDetailFactoryBean;}//2、创建 Trigger 对象:也是分为两种:下面是创建一个简单的 trigger//这里需要传入 JOB 对象,作为参数关联
/*    @Beanpublic SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){SimpleTriggerFactoryBean simpleTriggerFactoryBean = new SimpleTriggerFactoryBean();//获取 JobDetail 关联simpleTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());// 触发条件   该参数表示一个执行的毫秒数simpleTriggerFactoryBean.setRepeatInterval(2000);//设置重复次数simpleTriggerFactoryBean.setRepeatCount(5);return simpleTriggerFactoryBean;}*///通过 cron 表达式表示执行 trigger@Beanpublic CronTriggerFactoryBean cronTriggerFactoryBean(){CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();//获取 JobDetail 关联cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean().getObject());// 触发条件   该参数表示一个执行的毫秒数cronTriggerFactoryBean.setCronExpression("0/2 * * * * ?");return cronTriggerFactoryBean;}// 创建 scheduler 对象@Beanpublic SchedulerFactoryBean schedulerFactoryBean(){SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();//关联 TriggerschedulerFactoryBean.setTriggers(cronTriggerFactoryBean().getObject());return schedulerFactoryBean;}
}

【4】修改启动类

/*** 整合 Quartz*/
@SpringBootApplication
@EnableScheduling
public class ScheduledApplication {public static void main(String[] args) {SpringApplication.run(ScheduledApplication.class, args);}
}

四、Job 类中注入对象

【1】给 Job 类中注入 Service 类型的对象;

/***  定时任务类* @author zzx**/
public class QuartzDemo implements Job {@Autowiredprivate UserService userService;/*** 任务触发时所执行的方法*/public void execute(JobExecutionContext context) throws JobExecutionException {userService.test();System.out.println("任务调度"+new Date());}
}

【2】当运行时会出现空指针异常:userService 对象为空;

Caused by: java.lang.NullPointerException: nullat com.example.demo.scheduled.QuartzDemo.execute(QuartzDemo.java:25) ~[classes/:na]at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.0.jar:na]... 1 common frames omitted

【3】没有注入 userService 的原因如下,它是通过反射创建 Job 对象,并没有经过 SpringIOC 处理,所以依赖的对象不能通过 autowrite 注入;

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Class<?> jobClass = bundle.getJobDetail().getJobClass();return ReflectionUtils.accessibleConstructor(jobClass, new Class[0]).newInstance(new Object[0]);
}

【4】解决方案:重写创建 Job 的方式:并进行实例化 @Component;

@Component
public class MyAdaptableJobFactory extends AdaptableJobFactory {//将对象添加到SpringIoc容器中,并且完成该对象的属性注入@Autowiredprivate AutowireCapableBeanFactory autowireCapableBeanFactory;/*** 该方法需要将实例化的 job 对象手动添加到SpringIOC 容器中并且完成实例化;*/@Overridepublic Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object jobInstance = super.createJobInstance(bundle);//将该对象加入 IOC 容器中autowireCapableBeanFactory.autowireBean(jobInstance);return jobInstance;}
}

【5】 将其注入到 Quartz 的配置类中,注入到 SchedulerFactoryBean 中;

// 修改 SchedulerFactoryBean 类,set 创建 job 的factory 类
@Bean
public SchedulerFactoryBean schedulerFactoryBean(MyAdaptableJobFactory myAdaptableJobFactory){SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();//关联 TriggerschedulerFactoryBean.setTriggers(cronTriggerFactoryBean().getObject());schedulerFactoryBean.setJobFactory(myAdaptableJobFactory);return schedulerFactoryBean;
}

【6】测试结果:

【7】解决方案:在 SSM 的项目中可以通过如下方式获取依赖对象;

//根据spring的配置文件得到ioc容器对象
ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
Person person = context.getBean(Person.class);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/207711.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《opencv实用探索·六》简单理解图像膨胀

1、图像膨胀原理简单理解 膨胀是形态学最基本的操作&#xff0c;都是针对白色部分&#xff08;高亮部分&#xff09;而言的。膨胀就是使图像中高亮部分扩张&#xff0c;效果图拥有比原图更大的高亮区域。 2、图像膨胀的作用 注意一般情况下图像膨胀和腐蚀是联合使用的。 &…

Redis多机数据库

文章目录 Redis多机数据库一、主从复制1、旧版复制功能的实现a、同步b、命令传播 2、旧版复制功能的缺陷3、新版复制功能的实现a、部分同步功能b、复制实现步骤 4、心跳检测 二、哨兵1、Sentinel概念2、Sentinel初始化流程3、故障转移过程 三、集群1、几个概念2、集群创建流程a…

localStorage 和sessionStorage

localStorage 和 sessionStorage 是浏览器提供的两种客户端存储数据的方式&#xff1a; 生命周期&#xff1a; localStorage&#xff1a; 存储在 localStorage 中的数据在浏览器关闭后仍然保留&#xff0c;直到被显式删除或浏览器清除缓存。sessionStorage&#xff1a; 存储在 …

oops-framework框架 之 初始了解(一)

引擎&#xff1a;CocosCreator 环境&#xff1a; Mac Gitee: oops-framework 简介 oops-framework是由作者dgflash编写&#xff0c;基于CocosCreator 3.x而实现的开源框架。 该框架以插件形式存在&#xff0c;主要目的是为了降低与项目的耦合&#xff0c;并且通过插件内部的…

【QuickSort】单边快排思路及实现

思路&#xff1a; &#xff08;1&#xff09;首先定义一个递归函数&#xff1a;qucikSort(int [ ] arr,int l,int r)。函数的定义&#xff1a;给定一个数组arr&#xff0c;对它在[l,r]这个区间内的元素进行排序&#xff0c;从而使得整个数组在[l,r]这个区间内有序。 &#xff0…

电梯安全远程监控系统解决方案

一、方案背景 随着万丈高楼的平地起&#xff0c;电梯也成为了我们出入高层建筑最常用的工具之一。面对电梯数量的不断增加&#xff0c;电梯安全事故也是相继频发&#xff0c;因此关于电梯的安全运行就越来越受到社会各界的关注。电梯的使用在给人们出入高层建筑带来便利的同时&…

一种LED驱动专用控制电路方案

一、基本的概述 TM1651 是一种带键盘扫描接口的LED&#xff08;发光二极管显示器&#xff09;驱动控制专用电路&#xff0c;内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。本产品性能优良&#xff0c;质量可靠。采用SOP16/DIP16的封装形式。 二、特性说…

金蝶Apusic应用服务器 任意文件上传漏洞复现

0x01 产品简介 金蝶Apusic应用服务器&#xff08;Apusic Application Server&#xff0c;AAS&#xff09;是一款标准、安全、高效、集成并具丰富功能的企业级应用服务器软件&#xff0c;全面支持JakartaEE8/9的技术规范&#xff0c;提供满足该规范的Web容器、EJB容器以及WebSer…

快速筛出EXCEL行中的重复项

比如A列是一些恶意IP需要导入防火墙&#xff0c;但包括一些重复项&#xff0c;为不产生错误&#xff0c;需要把重复项筛出来&#xff1a; 1、给A列排序&#xff0c;让重复项的内容排在相邻的行 2、在B列中写一个条件函数&#xff1a;IF(A1A2,1,0)&#xff0c;然后下拉至行尾完成…

如何在 AdsPower 浏览器中设置代理

AdsPower是一款反检测指纹浏览器&#xff0c;来自中国开发团队的一款对电子商务营销人员非常有用的强大工具&#xff0c;同时具有出色的英语支持。AdsPower浏览器的主要优势是其价格便宜&#xff0c;与竞争对手相比&#xff0c;但其功能和整体工作表现甚至不逊于Indigo。 AdsP…

基于springboot+vue的点餐系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

IDEA编译器技巧-提示词忽略大小写

IDEA编译器技巧-提示词忽略大小写 写代码时,每次创建对象都要按住 Shift 字母 做大写开头, 废手, 下面通过编译器配置解放Shift 键 setting -> Editor -> General -> Code Completion -> Match case 把这个√去掉, 创建对象就不需要再按住 Shift 键 示例: 1.…

浅谈UML的概念和模型之UML九种图

1、用例图&#xff08;use case diagrams&#xff09; 【概念】描述用户需求&#xff0c;从用户的角度描述系统的功能 【描述方式】椭圆表示某个用例&#xff1b;人形符号表示角色 【目的】帮组开发团队以一种可视化的方式理解系统的功能需求 【用例图】 2、静态图 类图&…

ClassCMS2.4漏洞复现

CMS源码在附件中 环境搭建 使用phpstudy2016搭建web环境&#xff0c;php版本为5.5 安装CMS 这里选择Mysql数据库进行安装 用户名和密码都写默认的admin方便记忆 输入完成后点击安装 点击安装 CMS的安装过程中有个报错忽略就好&#xff0c;登录不进后台的话刷新一下页面 进入了C…

springboot数据格式验证——自定义日期格式验证及list验证

我们在工作中经常需要对日期格式进行定义&#xff0c;如果客户端传来的日期字符串不符合要求&#xff0c;那么根本无法保存&#xff0c;但是已有的注解并没有日期格式的验证&#xff0c;那我们就自己实现一个 一、自定义日期格式验证的注解DateFormat import javax.validatio…

Jquery动画特效

1&#xff0c;Jquery提供的特效方法 2&#xff0c;实例代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

反序列化漏洞详解(一)

目录 一、php面向对象 二、类 2.1 类的定义 2.2 类的修饰符介绍 三、序列化 3.1 序列化的作用 3.2 序列化之后的表达方式/格式 ① 简单序列化 ② 数组序列化 ③ 对象序列化 ④ 私有修饰符序列化 ⑤ 保护修饰符序列化 ⑥ 成员属性调用对象 序列化 四、反序列化 …

【C语言加油站】函数栈帧的创建与销毁 #保姆级讲解

函数栈帧的创建与销毁 导言一、计算机硬件1.冯•诺依曼机基本思想2.冯•诺依曼机的特点&#xff1a;3.存储器3.1 分类3.2 内存的工作方式3.3 内存的组成 4.寄存器4.1 基本含义4.2 寄存器的功能4.3 工作原理4.4 分类4.4.1 通用寄存器组AX(AH、AL)&#xff1a;累加器BX(BH、BL)&a…

【BEV感知 LSS方案】Lift-Splat-Shoot(LSS)

前言 LSS全称是Lift-Splat-Shoot&#xff0c;它先从车辆周围的多个摄像头拍摄到的图像进行特征提取&#xff0c;在特征图中估计出每个点的深度&#xff0c;然后把这些点“提升”到3D空间中。 接着&#xff0c;这些3D信息被放置到一个网格上&#xff0c;最后将这些信息“拍扁”…

Mybatis如何执行批量操作

文章目录 Mybatis如何执行批量操作使用foreach标签 使用ExecutorType.BATCH如何获取生成的主键 Mybatis如何执行批量操作 使用foreach标签 foreach的主要用在构建in条件中&#xff0c;它可以在SQL语句中进行迭代一个集合。foreach标签的属性主要有item&#xff0c;index&…