SpringBoot集成quartz实现定时任务(可修改cron表达式和传入参数)
创始人
2025-05-31 11:10:05

第一步创建SpringBoot项目的过程我就不在演示了!自己找找教程吧!

第二步,导入依赖:

 org.springframework.bootspring-boot-starter-quartzorg.springframework.bootspring-boot-starter-weborg.quartz-schedulerquartz2.3.0org.springframeworkspring-context-support5.3.8org.springframework.bootspring-boot-starter-jdbcmysqlmysql-connector-javaorg.springframework.bootspring-boot-starter-testtestorg.mybatis.spring.bootmybatis-spring-boot-starter2.2.2org.projectlomboklombok

第三步,启动类上加@EnableScheduling开启定时任务

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

第四步,创建QuartzService类

package com.example.quartz3.job;import java.util.*;import javax.annotation.PostConstruct;import lombok.extern.log4j.Log4j2;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.QuartzJobBean;/*** 调度service*/
@Configuration
@EnableScheduling
@Log4j2
public class QuartzService {@Autowiredprivate Scheduler scheduler;@PostConstructpublic void startScheduler() {try {scheduler.start();} catch (SchedulerException e) {e.printStackTrace();}}/*** 增加一个job** @param jobClass     任务实现类* @param jobName      任务名称* @param jobGroupName 任务组名* @param jobTime      时间表达式 (这是每隔多少秒为一次任务)* @param jobTimes     运行的次数 (<0:表示不限次数)*/public void addJob(Class jobClass, String jobName, String jobGroupName, int jobTime,int jobTimes) {try {// 任务名称和组构成任务keyJobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();// 使用simpleTrigger规则Trigger trigger = null;if (jobTimes < 0) {trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime)).startNow().build();} else {trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes)).startNow().build();}scheduler.scheduleJob(jobDetail, trigger);} catch (SchedulerException e) {e.printStackTrace();}}/*** 增加一个job** @param jobClass     任务实现类* @param jobName      任务名称* @param jobGroupName 任务组名* @param jobTime      时间表达式 (如:0/5 * * * * ? )*/public void addJob(Class jobClass, String jobName, String jobGroupName, String jobTime,Integer userId) {try {// 创建jobDetail实例,绑定Job实现类// 指明job的名称,所在组的名称,以及绑定job类// 任务名称和组构成任务keyJobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).usingJobData("userId",userId)//可以使用usingJobData添加传入的参数,辅助后面job任务的业务实现.build();// 定义调度触发规则// 使用cornTrigger规则// 触发器keyTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND)).withSchedule(CronScheduleBuilder.cronSchedule(jobTime).inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))).startNow().build();// 把作业和触发器注册到任务调度中scheduler.scheduleJob(jobDetail, trigger);if(!scheduler.isShutdown()){scheduler.start();}} catch (Exception e) {e.printStackTrace();}}/*** 修改 一个job的 时间表达式*/public void updateJob(String jobName, String jobGroupName, String jobTime) {try {log.warn("Start update job ,job name is {}, jobCron is {}", jobName, jobTime);TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(jobTime).inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))).build();// 重启触发器scheduler.rescheduleJob(triggerKey, trigger);log.warn("finish update job!");} catch (SchedulerException e) {e.printStackTrace();}}/*** 删除任务一个job** @param jobName      任务名称* @param jobGroupName 任务组名*/public void deleteJob(String jobName, String jobGroupName) {try {scheduler.deleteJob(new JobKey(jobName, jobGroupName));} catch (Exception e) {e.printStackTrace();}}/*** 暂停一个job** @param jobName jobName* @param jobGroupName jobName*/public void pauseJob(String jobName, String jobGroupName) {try {JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);scheduler.pauseJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 恢复一个job** @param jobName jobName* @param jobGroupName jobGroupName*/public void resumeJob(String jobName, String jobGroupName) {try {JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);scheduler.resumeJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 立即执行一个job** @param jobName jobName* @param jobGroupName jobGroupName*/public void runAJobNow(String jobName, String jobGroupName) {try {JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);scheduler.triggerJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 获取所有计划中的任务列表** @return List*/public List> queryAllJob() {List> jobList = null;try {GroupMatcher matcher = GroupMatcher.anyJobGroup();Set jobKeys = scheduler.getJobKeys(matcher);jobList = new ArrayList>();for (JobKey jobKey : jobKeys) {List triggers = scheduler.getTriggersOfJob(jobKey);for (Trigger trigger : triggers) {Map map = new HashMap<>();map.put("jobName", jobKey.getName());map.put("jobGroupName", jobKey.getGroup());map.put("description", "触发器:" + trigger.getKey());Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());map.put("jobStatus", triggerState.name());if (trigger instanceof CronTrigger) {CronTrigger cronTrigger = (CronTrigger) trigger;String cronExpression = cronTrigger.getCronExpression();map.put("jobTime", cronExpression);}jobList.add(map);}}} catch (SchedulerException e) {e.printStackTrace();}return jobList;}/*** 获取所有正在运行的job** @return List*/public List> queryRunJob() {List> jobList = null;try {List executingJobs = scheduler.getCurrentlyExecutingJobs();jobList = new ArrayList>(executingJobs.size());for (JobExecutionContext executingJob : executingJobs) {Map map = new HashMap();JobDetail jobDetail = executingJob.getJobDetail();JobKey jobKey = jobDetail.getKey();Trigger trigger = executingJob.getTrigger();map.put("jobName", jobKey.getName());map.put("jobGroupName", jobKey.getGroup());map.put("description", "触发器:" + trigger.getKey());Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());map.put("jobStatus", triggerState.name());if (trigger instanceof CronTrigger) {CronTrigger cronTrigger = (CronTrigger) trigger;String cronExpression = cronTrigger.getCronExpression();map.put("jobTime", cronExpression);}jobList.add(map);}} catch (SchedulerException e) {e.printStackTrace();}return jobList;}}

第五步,创建自己的Job类实现自己的业务逻辑

package com.example.quartz3.job;import com.example.quartz3.domain.User;
import com.example.quartz3.mapper.UserMapper;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;import java.util.Date;/*** 定时全量备份job*/
@Component
@Log4j2
public class SomThingTimeJob extends QuartzJobBean {@Autowiredprivate UserMapper userMapper;@Autowiredprivate QuartzService quartzService;@SneakyThrows@Overrideprotected void executeInternal(JobExecutionContext context) throws JobExecutionException {log.warn("start SomThingTimeJob !! ");//写自己要实现的业务逻辑Integer userId = (Integer) context.getJobDetail().getJobDataMap().get("userId");//可以使用getJobDetail的getJobDataMap方法获取传入的其他参数辅助自己的业务实现User users = userMapper.selectUserById(userId);System.out.println(new Date()+"用户姓名"+users.getUserName());log.warn("finish SomThingTimeJob !! ");}
}

第六步,Cron表达式转换工具类

package com.example.quartz3.utils;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author 一个达不刘* cron表达式生成工具类**/
public class CronUtil {/*** 生成指定格式日期字符** @param date       日期* @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss* @return formatTimeStr*/public static String formatDateByPattern(Date date, String dateFormat) {dateFormat = dateFormat == null ? "yyyy-MM-dd HH:mm:ss" : dateFormat;SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);return date != null ? sdf.format(date) : null;}/*** 生成cron表达式 ss mm HH dd MM ? yyyy* convert Date to cron ,eg.  "0 06 10 15 1 ? 2014"** @param date : 时间点*/public static String getCron(Date date) {String dateFormat = "ss mm HH dd MM ? yyyy";return formatDateByPattern(date, dateFormat);}/*** 生成cron表达式 ss mm HH dd MM ?* convert Date to cron ,eg.  "0 06 10 15 1 ?"** @param date : 时间点* @param type : 类型 日/周/月*/public static String getLoopCron(Date date, String type, Integer week, Integer day) {String dateFormat = "ss mm HH";//  dd MM ?String cron = formatDateByPattern(date, dateFormat);switch (type) {case "Day":return cron + " * * ?";case "Week":return cron + " ? * " + getCurrentWeek(week);case "Month":return cron + " " + day + " * ?";default:return "false";}}/*** 获取当前星期的字符 MON TUE WED THU FRI SAT SUN** @param week : 周 1 2 3 4 5 6 7* @return 星期字符*/public static String getCurrentWeek(Integer week) {String[] weeks = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};return weeks[week - 1];}public static void main(String[] args) {Date date = new Date();//String dateFormat = "ss mm HH dd MM ? yyyy";//String cron = formatDateByPattern(date, dateFormat);//System.out.println("原始:" + cron);////String day = formatDateByPattern(date, "ss mm HH");//System.out.println("日报:" + day + " * * ?");//0 15 10 ? * MON 每周一上午10点15分动参为 周//String week = formatDateByPattern(date, "ss mm HH");//System.out.println("周报:" + week + " ? * MON");//0 15 9 10 * ? 每月10号9点15分动参为 号//String month = formatDateByPattern(date, "ss mm HH");//System.out.println("月报:" + month + " 10 * ?");}
}

第七步,创建字符串转换成类的转换器

package com.example.quartz3.utils;import org.springframework.scheduling.quartz.QuartzJobBean;/*** @author 一个达不刘* @date 2023/3/20 18:34*/
public class ClassUtil {@SuppressWarnings("unchecked")public static Class getClass(String classname) throws Exception {Class class1 = Class.forName(classname);return (Class) class1;}
}

为什么使用这个转换器的原因是创建job的时候

public void addJob(Class jobClass, String jobName, String jobGroupName, int jobTime,int jobTimes)

jobClass是一个.class的对象,但是传入的参数不可能是一个.class的对象,所以需要一个转换器

第八步,创建controller控制层

package com.example.quartz3.controller;import com.example.quartz3.job.QuartzService;
import com.example.quartz3.utils.ClassUtil;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;/*** @author 钟于一个达不刘*/
@RestController
@RequestMapping(value = "/job")
public class JobController {@Autowiredprivate QuartzService quartzService;/*** @param jobClassName* @param jobGroupName* @param cronExpression* @throws Exception*/@PostMapping(value = "/addjob")public void addjob(@RequestParam(value = "jobClassName") String jobClassName,@RequestParam(value = "jobGroupName") String jobGroupName,@RequestParam(value = "cronExpression") String cronExpression,@RequestParam("userId") Integer userId) throws Exception {quartzService.addJob(ClassUtil.getClass(jobClassName), jobClassName, jobGroupName, cronExpression,userId);}/*** @param jobClassName* @param jobGroupName* @throws Exception*/@PostMapping(value = "/pausejob")public void pausejob(@RequestParam(value = "jobClassName") String jobClassName,@RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {quartzService.pauseJob(jobClassName, jobGroupName);}/*** @param jobClassName* @param jobGroupName* @throws Exception*/@PostMapping(value = "/resumejob")public void resumejob(@RequestParam(value = "jobClassName") String jobClassName,@RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {quartzService.resumeJob(jobClassName, jobGroupName);}/*** @param jobClassName* @param jobGroupName* @throws Exception*/@PostMapping(value = "/deletejob")public void deletejob(@RequestParam(value = "jobClassName") String jobClassName,@RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {quartzService.deleteJob(jobClassName, jobGroupName);}}

第九步,创建User实体类

package com.example.quartz3.mapper;import com.example.quartz3.domain.User;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** @author 一个达不刘* @date 2023/3/19 19:28*/
@Mapper
public interface UserMapper {List selectList(Object o);int insertUser(User user);User selectUserById(int id);
}

第十步,创建mapper文件进行测试

package com.example.quartz3.mapper;import com.example.quartz3.domain.User;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** @author 一个达不刘* @date 2023/3/19 19:28*/
@Mapper
public interface UserMapper {List selectList(Object o);int insertUser(User user);User selectUserById(int id);
}

第十一步,测试

 

有志向于IT技术的小伙伴,或者想要一些IT技术的资料,可以来QQ群获取:526519295

相关内容

热门资讯

【开源协议】关于6种开源协议的... 关于开源协议的说明前言开源协议分为 宽松型 和 著作权型。如何选择?开源协议(GPL,...
easymock不能用了?fa... 什么是fast mock 前端常常要等待后面接口写好后,才能集成测试,免...
GIS的一些简单算法(自己作记... 一、线的矢量算法 1、简单的线相交算法 算法1:快速排斥与矢量跨立         快...
催债令来了!国家急了,严禁机关... 作者 | 剑书发现没有,当前国家摆在最高优先级的一件大事,竟然是给中小企业还清欠款。就在6月1日,国...
数据分析思维|思考问题的25个... 逻辑思维:能够理性分析问题,梳理出问题的本质和关键点,建立...
三、Docker:Compos...   Docker-compose 是用于定义和运行多容器 Docker 应用程序的编排工具。使用 d...
理想汽车5月交付40856辆,... 新京报贝壳财经讯 6月1日,理想汽车公布2025年5月交付数据。5月份,理想汽车交付新车40856辆...
新宙邦:公司对高性能电子材料均... 证券日报网讯 新宙邦5月30日在互动平台回答投资者提问时表示,公司对高性能电子材料均做了一些布局。其...
电商酒水类产品打假有哪些操作(... 线上酒水类产品蓬勃发展,但产品假货问题也随之而来,不仅损害了品牌商家的合法权益,还对消费者的健康和安...
今年很火的AI绘画怎么玩 1.前言 2022年绝对可以说是AIGC元年,从google搜索的趋势来看࿰...
canvas 教程 指南 万字... 前端妹子问我为什么官网上面只有一个canvas标签,里面什么都没有… 我脸色一变”完了...
开发一个app需要多少钱 APP应用开发主要分为原生APP和HTML5APP开发,使用HTML5开发的app价格...
vue项目的创建 npm install postcss postcss-pxtorem --save-dev 什么是...
二十六、对象的实例化内存布局与... 一、对象的实例化 1.判断对象对用的类是否加载、链接、初始化。 2.为对象分配内存。 3.处理并发...
助力私募行业高质量发展,华西证...   践行传播行业文化,进一步促进私募行业高质量发展,资本市场这场现象级行...
创建索引,解决mysql数据查... 实战场景 :两个表 T_PLATFORM A left join T_OPER_REC...
5. Python中的异常处理... 1. 说明: 自己写的代码保证万无一失有点难度,代码报出异常后ÿ...
图神经网络(GCN) 一、GCN的起源 曾经深度学习一直都是被几大经典模型给统治着,如CNN、RNN等等&#...
5月汽车销量出炉:理想力压小鹏... 【市场】6月第一天,多家汽车企业公布了5月的销量数据,和去年相比实现了两位数增长,但排名发生了变化。...
Python数据结构与算法(p... 主要内容:什么是列表查找顺序查找二分查找一、什么是查找?(...
状态机DP 状态机DP算法特征子数组类DP问题的定义:以最后一个元素结尾的最大xxx特征1...
mendeley管理文献样式 编辑GB/T 7714—2005参考文件样式,解决:显示大小写ÿ...
多次谋求A股上市!锂电巨头业绩... 知名锂电池生产企业天津力神电池股份有限公司(下称“天津力神”)的经营情况曝光。证券时报·e公司记者在...
前沿技术揭秘:云原生-展望容器... 2023年最火热的就是ChatGPT,当然还有5G技术、AI、机器学习、区块链等技术。另外还有一个现...
WalletConnect的下... 加密行业中每一个项目都有它自己的作用,很多我们意想不到或者认为的事情往往最后都会出现转...
独家 | 大润发佘咸平任永辉C... 交流永辉,实名添加微信lihua759321进群多位市场人士向《商业观察家》确认,大润发M会员店商品...
拼多多管理层多次强调利润不可持... 近日,拼多多一季度财报引起市场热议。财报显示,拼多多一季度营收957亿元,同比增长10%,归母净利润...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
矿泉水瓶装大米,便利店能增收3... 矿泉水瓶装大米,便利店能增收300万 把大米装进矿泉水瓶,一瓶卖到60块...
港股迎来打新热!“散户失权”引... 港股行情提振,新股表现亮眼,打新又热了。Wind显示,2025年港股已迎来27只新股,其中仅7只上市...