记一次ruoyi中使用Quartz实现定时任务

一、首先了解一下Quartz

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

二、Quartz的三大核心组件

调度器:Scheduler。
****任务:JobDetail。
**触发器:**Trigger,包括 SimpleTrigger 和 CronTrigger。
(1)**Job(任务):**是一个接口,有一个方法 void execute(JobExecutionContext context) ,可以通过实现该接口来定义需要执行的任务(具体的逻辑代码)。

JobDetail:Quartz每次执行Job时,都重新创建一个Job实例,会接收一个Job实现类,以便运行的时候通过newInstance()的反射调用机制去实例化Job。JobDetail是用来描述Job实现类以及相关静态信息,比如任务在scheduler中的组名等信息。

(2)Trigger(触发器):描述触发Job执行的时间触发规则实现类SimpleTrigger和CronTrigger可以通过crom表达式定义出各种复杂的调度方案。

Calendar:是一些日历特定时间的集合。一个Trigger可以和多个 calendar关联,比如每周一早上10:00执行任务,法定假日不执行,则可以通过calendar进行定点排除。

(3)Scheduler(调度器):代表一个Quartz的独立运行容器。Trigger和JobDetail可以注册到Scheduler中。Scheduler可以将Trigger绑定到某一JobDetail上,这样当Trigger被触发时,对应的Job就会执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
在这里插入图片描述

三、简单实现

引入依赖:

<!-- SpringBoot 整合 Quartz 定时任务 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>2.3.5.RELEASE</version>
</dependency>
package com.pjb.job;import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;import java.text.SimpleDateFormat;
import java.util.Date;/*** 同步用户信息Job* @author pan_junbiao**/
public class SyncUserJob extends QuartzJobBean
{@Overrideprotected void executeInternal(JobExecutionContext jobExecutionContext){//获取JobDetail中传递的参数String userName = (String) jobExecutionContext.getJobDetail().getJobDataMap().get("userName");String blogUrl = (String) jobExecutionContext.getJobDetail().getJobDataMap().get("blogUrl");String blogRemark = (String) jobExecutionContext.getJobDetail().getJobDataMap().get("blogRemark");//获取当前时间Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//打印信息System.out.println("用户名称:" + userName);System.out.println("博客地址:" + blogUrl);System.out.println("博客信息:" + blogRemark);System.out.println("当前时间:" + dateFormat.format(date));System.out.println("----------------------------------------");}
}
package com.pjb.config;import com.pjb.job.SyncUserJob;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Quartz定时任务配置类* @author pan_junbiao**/
@Configuration
public class QuartzConfig
{private static String JOB_GROUP_NAME = "PJB_JOBGROUP_NAME";private static String TRIGGER_GROUP_NAME = "PJB_TRIGGERGROUP_NAME";/*** 定时任务1:* 同步用户信息Job(任务详情)*/@Beanpublic JobDetail syncUserJobDetail(){JobDetail jobDetail = JobBuilder.newJob(SyncUserJob.class).withIdentity("syncUserJobDetail",JOB_GROUP_NAME).usingJobData("userName", "pan_junbiao的博客") //设置参数(键值对).usingJobData("blogUrl","https://blog.csdn.net/pan_junbiao").usingJobData("blogRemark","您好,欢迎访问 pan_junbiao的博客").storeDurably() //即使没有Trigger关联时,也不需要删除该JobDetail.build();return jobDetail;}/*** 定时任务1:* 同步用户信息Job(触发器)*/@Beanpublic Trigger syncUserJobTrigger(){//每隔5秒执行一次CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");//创建触发器Trigger trigger = TriggerBuilder.newTrigger().forJob(syncUserJobDetail())//关联上述的JobDetail.withIdentity("syncUserJobTrigger",TRIGGER_GROUP_NAME)//给Trigger起个名字.withSchedule(cronScheduleBuilder).build();return trigger;}
}

执行结果:
在这里插入图片描述

四、在若依中实现

在这里插入图片描述
在这里插入图片描述
对应后台代码:
controller:

 /*** 新增保存调度*/@Log(title = "定时任务", businessType = BusinessType.INSERT)@RequiresPermissions("monitor:job:add")@PostMapping("/add")@ResponseBodypublic AjaxResult addSave(@Validated SysJob job) throws SchedulerException, TaskException{if (!CronUtils.isValid(job.getCronExpression())){return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确");}else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)){return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用");}else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })){return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用");}else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })){return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用");}else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)){return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规");}else if (!ScheduleUtils.whiteList(job.getInvokeTarget())){return error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");}job.setCreateBy(getLoginName());return toAjax(jobService.insertJob(job));}

对应实现;

  /*** 新增任务* * @param job 调度信息 调度信息*/@Override@Transactional(rollbackFor = Exception.class)public int insertJob(SysJob job) throws SchedulerException, TaskException{job.setStatus(ScheduleConstants.Status.PAUSE.getValue());int rows = jobMapper.insertJob(job);if (rows > 0){ScheduleUtils.createScheduleJob(scheduler, job);}return rows;}

具体看这个方法:
ScheduleUtils.createScheduleJob(scheduler, job);
在这里插入图片描述
具体进入getQuartzJobClass方法:
在这里插入图片描述
这里分了两个类,一个是可以异步执行,另一个是不可以异步执行(也就是同一个job对象,不能同时进行,需要等待,一般不会这么用);
其实两个类基本一样,都是继承了AbstractQuartzJob类(这个类实现了Job,指向具体干什么,也就是实现Job的doExecute()方法),不同之处就是禁止并发使用了@DisallowConcurrentExecution注解;

在这里插入图片描述
这个invokeMethod()方法不说了,就是用反射,执行我们指定的类、方法;

整体流程就是这么简单,具体的暂停、激活,使用scheduler类中的方法,结合我们定义的jobKey去操作,类似于下面:
scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));

五、程序启动时加载数据库中的定时任务

就是使用@PostConstruct,在springboot启动后立刻执行方法:

 /*** 项目启动时,初始化定时器 * 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)*/@PostConstructpublic void init() throws SchedulerException, TaskException{scheduler.clear();List<SysJob> jobList = jobMapper.selectJobAll();for (SysJob job : jobList){ScheduleUtils.createScheduleJob(scheduler, job);}}

引入别人的图片:
在这里插入图片描述

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

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

相关文章

PostgreSQL学习总结(13)—— PostgreSQL 目录结构与配置文件 postgresql.conf 详解

环境搭建完成后&#xff0c;从环境变量里看它涉及的目录 export PGHOME/usr/local/pgsql/ export PGUSERpostgres export PGPORT5432 export PGDATA/app/pgsql/data export PGLOG/app/pgsql/log/postgres.log export PATH$PGHOME/bin:$PATH:$HOME/bin export LD_LIBRARY_PATH$…

UE4/5AI制作基础AI跳跃(适合新手)

目录 制作 添加逻辑 添加导航链接代理 结果 在上一章中&#xff0c;我们讲解了简单的AI跟随玩家&#xff0c;制作了一个基础的ai。 UE4/5AI制作基础AI&#xff08;适合新手入门&#xff0c;运用黑板&#xff0c;行为树&#xff0c;ai控制器&#xff0c;角色类&#xff0c;任…

C++ 程序设计:四大模式(工厂+装饰+策略+观察者)

1.前言 "工厂装饰策略观察者"是常见且常用的设计模式之一&#xff0c;但并不是指称"四大模式"的官方术语。 "四大模式"通常是指指令式面向对象编程中的四个基本概念&#xff1a;封装、继承、多态和抽象。这四个概念是面向对象编程的基石。 2.工…

Ubuntu 命令行编辑文件后如何保存退出

在 Ubuntu 命令行中编辑文件后&#xff0c;可以使用以下步骤保存并退出&#xff1a; 按下键盘上的 Ctrl 键和 X 键组合&#xff0c;以退出编辑模式。如果文件已更改&#xff0c;你将看到提示&#xff0c;询问是否保存更改。按下 Y 键来确认保存更改&#xff0c;或按下 N 键取消…

4、深入理解ribbon

一、负载均衡的两种方式 服务器端负载均衡 传统的方式前端发送请求会到我们的的nginx上去&#xff0c;nginx作为反向代理&#xff0c;然后路由给后端的服务器&#xff0c;由于负载均衡算法是nginx提供的&#xff0c;而nginx是部署到服务器端的&#xff0c;所以这种方式又被称为…

linux之Ubuntu系列(-)常见指令 重定向

Ubuntu 中文 版本 注意点 通过修改语言改成英文 在终端录入&#xff1a;export LANGen_US 在终端录入&#xff1a;xdg-user-dirs-gtk-update 单用户和多用户 命令格式 command [-选项] [参数] –查看命令的帮助 命令 --help man 命令 |操作键| 功能| |空格键|-显示手册的下…

合并修改缺陷分支的commit到master分支

合并修改缺陷分支的commit到master分支 当我们在修改缺陷的时候&#xff0c;我们会开辟一个分支&#xff0c;专门用来修改缺陷例如hotfix 当我们在hotfix上commit的代码&#xff0c;想要合并到master分支&#xff0c;这时我们要怎么处理呢 我们使用 git cherry-pick&#xff1…

OSS对象存储后端实现+Vue实现图片上传【基于若依管理系统开发】

文章目录 基本介绍术语介绍图片上传方式介绍普通上传用户直传应用服务器签名后直传 OSS对象存储后端实现maven配置文件配置类ServiceController 图片上传前端图片上传组件api页面使用组件组件效果 基本介绍 术语介绍 Bucket&#xff08;存储空间&#xff09;&#xff1a;用于…

【论文】基于GANs的图像文字擦除 ——2010.EraseNet: End-to-End Text Removal in the Wild(已开源)

pytorch官方代码&#xff1a;https://github.com/lcy0604/EraseNet 论文&#xff1a;2010.EraseNet: End-to-End Text Removal in the Wild 网盘提取码&#xff1a;0719 一、图片文字去除效果 图10 SCUT-EnsText 真实数据集的去除 第一列原图带文字、第二列为去除后的标签&a…

爆肝整理,Postman接口测试-全局变量/接口关联/加密/解密(超细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 全局变量和环境变…

[华为OD] 污染水域(多源BFS)

救命&#xff0c;因为实在找不到工作。。。 所以已经开始准备华为OD的笔试题了。。。 但是内心深处不是很想去OD呜呜呜 文章目录 BFS与多源BFS污染水域leetcode 1162:&#xff1a;地图分析leetcode 542&#xff1a;01矩阵leetcode 1020&#xff1a;飞地的数量 BFS与多源BFS BF…

AJAX:宏任务与微任务

异步任务划分为了 宏任务&#xff1a;由浏览器环境执行的异步代码 微任务&#xff1a;由 JS 引擎环境执行的异步代码 宏任务和微任务具体划分&#xff1a; 左边表格是宏任务&#xff0c;右边是微任务 事件循环模型 /*** 目标&#xff1a;阅读并回答打印的执行顺序 */ console…

Spark编程-键值对RDD(K,V)创建及常用操作

简述 SparkRDD中可以包含任何类型的对象&#xff0c;在实际应用中&#xff0c;“键值对”是一种比较常见的RDD元素类型&#xff0c;分组和聚合操作中经常会用到&#xff0c;尤其是groupByKey和reduceByKey。 Spark操作中经常会用到“键值对RDD”&#xff08;Pair RDD&a…

CSS样式

1.高度和宽度 .c1{height:300px;width:500px;}注意事项&#xff1a; 宽度支持百分比&#xff0c;高度不支持。行内标签&#xff1a;默认无效会计标签&#xff1a;默认有效&#xff08;霸道&#xff0c;右侧区域空白&#xff0c;也不给你用&#xff09; 2.块级和行内标签 块…

【Django学习】(十四)自定义action_router

之前我们的视图类可以继承GenericViewSet或者ModelViewSet&#xff0c;我们不用再自定义通用的action方法&#xff0c;但是有时候我们需要自定义action&#xff0c;我们该如何设计呢&#xff1f; 自定义action 1、手写视图逻辑 1.1、先在视图集里自定义action方法&#xff0…

HCIP第十二天(笔记)

企业网的三层架构 园区 --- 工厂、政府机关、商城、校园、公园等公共场所&#xff0c;为了实现数据的互通&#xff0c;所搭建的网络都可以称为是园区网 接入层 使用二层交换机 --- 依靠MAC地址表进行转发的设备 WLAN --- 无线局域网 --- 广义上指以无线电波、激光…

GO语言泛型

set一般没什么不方便的 但是使用GET 需要使用类型断言,将取出来的数据转为预期数据, 空接口本身是一个装箱,会产生内存逃逸和多一部分空间. 于是1.17GO使用泛型. 泛型实现: 分析可执行文件后:发现 也就是泛型会为每个数据类型都生产一套代码,导致可执行文件大小增加,并且使用…

uni-app中a标签下载文件跳转后左上角默认返回键无法继续返回

1.首先使用的是onBackPress //跟onShow同级别 onBackPress(option){ uni.switchTab({ url:/pages/....... return true }) }发现其在uni默认头部中使用是可以的 但是h5使用了"navigationStyle":"custom"后手机默认的返回并不可以&#xff0c; 2.经过查询…

LCD-STM32液晶显示中英文-(5.字符编码)

目录 字符编码 字符编码说明参考网站 字符编码 ASCII编码 ASCII编码介绍 ASCII编码表 中文编码 1. GB2312标准 区位码 2. GBK编码 3. GB18030 各个标准的对比说明 4. Big5编码 字符编码 字符编码说明参考网站 字符编码及转换测试&#xff1a;导航菜单 - 千千秀字 …

智迪科技在创业板上市:市值约31亿元,谢伟明和黎柏松为实控人

7月17日&#xff0c;珠海市智迪科技股份有限公司&#xff08;下称“智迪科技”&#xff0c;SZ:301503&#xff09;在深圳证券交易所创业板上市。本次上市&#xff0c;智迪科技的发行价为31.59元/股&#xff0c;发行数量为2000万股&#xff0c;募资总额约为6.32亿元&#xff0c;…