1:在项目的pom文件添加quartz依赖

<!-- quartz定时任务 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2:修改application.yml文件

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/quartzJob?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaipassword: rootusername: rootdriver-class-name: com.mysql.cj.jdbc.Driverquartz:job-store-type: jdbcjdbc:initialize-schema: always

参照yml文件

spring:## quartz定时任务,采用数据库方式quartz:job-store-type: jdbcinitialize-schema: embedded#定时任务启动开关,true-开  false-关auto-startup: true#延迟1秒启动定时任务startup-delay: 1s#启动时更新己存在的Joboverwrite-existing-jobs: trueproperties:org:quartz:scheduler:instanceName: MySchedulerinstanceId: AUTOjobStore:class: org.springframework.scheduling.quartz.LocalDataSourceJobStoredriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatetablePrefix: QRTZ_isClustered: falsemisfireThreshold: 12000clusterCheckinInterval: 15000threadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true

注意:

1、如果需要quartz 第一次运行时自动生成 quartz 所需的表那么 quartzJob? 后面的配置为 :allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai

待第一次运行后可以再根据自己的需要修改

2、配置文件中的 initialize-schema: always 配置的 always 属性意思是,每次初始化都会重新生成表(执行一次删除,执行一次创建),生成后,可以修改为 never

只有以上两个条件同时配置满足,才能使quartz 在第一次运行时,自动生成所需的表

3-1:方法1:启动项目就会在数据库生成11张表,如下图,点击查看各表详细介绍

3-2:方法2:也可以直接执行 Quartz 需要的SQL文件,生成11张quartz需要的表

在quartz的ja包org.quartz.impl.jdbcjobstore路径下,如下图

4:在此基础上,我们再额外增加一张表,与我们可能有业务关联的信息整合

Sql语句建表

CREATE TABLE `sys_quartz_job` (`id` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`create_by` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建人',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`del_flag` int DEFAULT NULL COMMENT '删除状态',`update_by` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '修改人',`update_time` datetime DEFAULT NULL COMMENT '修改时间',`job_class_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '任务类名',`cron_expression` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 'cron表达式',`parameter` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '参数',`meeting_record_id` int DEFAULT NULL COMMENT '会议室记录id',`description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '描述',`status` int DEFAULT NULL COMMENT '状态 0正常 -1停止',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;

5:创建quartz项目图

6:Controller

package org.jeecg.modules.quartz.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.jeecg.modules.quartz.service.IQuartzJobService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;/*** @Description: 定时任务*/
@RestController
@RequestMapping("/sys/quartzJob")
@Slf4j
@Api(tags = "定时任务接口")
public class QuartzJobController {@Autowiredprivate IQuartzJobService quartzJobService;@Autowiredprivate Scheduler scheduler;/*** 分页列表查询* * @param quartzJob* @param pageNo* @param pageSize* @param req* @return*/@RequestMapping(value = "/list", method = RequestMethod.GET)public Result<?> queryPageList(QuartzJob quartzJob, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, req.getParameterMap());Page<QuartzJob> page = new Page<QuartzJob>(pageNo, pageSize);IPage<QuartzJob> pageList = quartzJobService.page(page, queryWrapper);return Result.ok(pageList);}/*** 添加定时任务* * @param quartzJob* @return*///@RequiresRoles("admin")@RequestMapping(value = "/add", method = RequestMethod.POST)public Result<?> add(@RequestBody QuartzJob quartzJob) {quartzJobService.saveAndScheduleJob(quartzJob);return Result.ok("创建定时任务成功");}/*** 更新定时任务* * @param quartzJob* @return*///@RequiresRoles("admin")@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})public Result<?> eidt(@RequestBody QuartzJob quartzJob) {try {quartzJobService.editAndScheduleJob(quartzJob);} catch (SchedulerException e) {log.error(e.getMessage(),e);return Result.error("更新定时任务失败!");}return Result.ok("更新定时任务成功!");}/*** 通过id删除* * @param id* @return*///@RequiresRoles("admin")@RequestMapping(value = "/delete", method = RequestMethod.DELETE)public Result<?> delete(@RequestParam(name = "id", required = true) String id) {QuartzJob quartzJob = quartzJobService.getById(id);if (quartzJob == null) {return Result.error("未找到对应实体");}quartzJobService.deleteAndStopJob(id);return Result.ok("删除成功!");}/*** 批量删除* * @param ids* @return*///@RequiresRoles("admin")@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {if (ids == null || "".equals(ids.trim())) {return Result.error("参数不识别!");}for (String id : Arrays.asList(ids.split(SymbolConstant.COMMA))) {QuartzJob job = quartzJobService.getById(id);quartzJobService.deleteAndStopJob(id);}return Result.ok("删除定时任务成功!");}/*** 暂停定时任务* * @param id* @return*///@RequiresRoles("admin")@GetMapping(value = "/pause")@ApiOperation(value = "停止定时任务")public Result<Object> pauseJob(@RequestParam(name = "id") String id) {QuartzJob job = quartzJobService.getById(id);if (job == null) {return Result.error("定时任务不存在!");}quartzJobService.pause(job);return Result.ok("停止定时任务成功");}/*** 启动定时任务* * @param id* @return*///@RequiresRoles("admin")@GetMapping(value = "/resume")@ApiOperation(value = "启动定时任务")public Result<Object> resumeJob(@RequestParam(name = "id") String id) {QuartzJob job = quartzJobService.getById(id);if (job == null) {return Result.error("定时任务不存在!");}quartzJobService.resumeJob(job);//scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));return Result.ok("启动定时任务成功");}/*** 通过id查询* * @param id* @return*/@RequestMapping(value = "/queryById", method = RequestMethod.GET)public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {QuartzJob quartzJob = quartzJobService.getById(id);return Result.ok(quartzJob);}/*** 导出excel* * @param request* @param quartzJob*/@RequestMapping(value = "/exportXls")public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {// Step.1 组装查询条件QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());// Step.2 AutoPoi 导出ExcelModelAndView mv = new ModelAndView(new JeecgEntityExcelView());List<QuartzJob> pageList = quartzJobService.list(queryWrapper);// 导出文件名称mv.addObject(NormalExcelConstants.FILE_NAME, "定时任务列表");mv.addObject(NormalExcelConstants.CLASS, QuartzJob.class);//获取当前登录用户//update-begin---author:wangshuai ---date:20211227  for:[JTC-116]导出人写死了------------LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("定时任务列表数据", "导出人:"+user.getRealname(), "导出信息"));//update-end---author:wangshuai ---date:20211227  for:[JTC-116]导出人写死了------------mv.addObject(NormalExcelConstants.DATA_LIST, pageList);return mv;}/*** 通过excel导入数据* * @param request* @param response* @return*/@RequestMapping(value = "/importExcel", method = RequestMethod.POST)public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();// 错误信息List<String> errorMessage = new ArrayList<>();int successLines = 0, errorLines = 0;for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {// 获取上传文件对象MultipartFile file = entity.getValue();ImportParams params = new ImportParams();params.setTitleRows(2);params.setHeadRows(1);params.setNeedSave(true);try {List<QuartzJob> listQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);//add-begin-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986for(QuartzJob job: listQuartzJobs){job.setStatus(CommonConstant.STATUS_DISABLE);}List<String> list = ImportExcelUtil.importDateSave(listQuartzJobs, IQuartzJobService.class, errorMessage,CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME);//add-end-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986errorLines+=list.size();successLines+=(listQuartzJobs.size()-errorLines);} catch (Exception e) {log.error(e.getMessage(), e);return Result.error("文件导入失败!");} finally {try {file.getInputStream().close();} catch (IOException e) {e.printStackTrace();}}}return ImportExcelUtil.imporReturnRes(errorLines,successLines,errorMessage);}/*** 立即执行* @param id* @return*///@RequiresRoles("admin")@GetMapping("/execute")public Result<?> execute(@RequestParam(name = "id", required = true) String id) {QuartzJob quartzJob = quartzJobService.getById(id);if (quartzJob == null) {return Result.error("未找到对应实体");}try {quartzJobService.execute(quartzJob);} catch (Exception e) {//e.printStackTrace();log.info("定时任务 立即执行失败>>"+e.getMessage());return Result.error("执行失败!");}return Result.ok("执行成功!");}}

7:Service

package org.jeecg.modules.quartz.service;import java.util.List;import org.jeecg.modules.quartz.entity.QuartzJob;
import org.quartz.SchedulerException;import com.baomidou.mybatisplus.extension.service.IService;/*** @Description: 定时任务*/
public interface IQuartzJobService extends IService<QuartzJob> {/*** 通过类名寻找定时任务* @param jobClassName 类名* @return List<QuartzJob>*/List<QuartzJob> findByJobClassName(String jobClassName);/*** 保存定时任务* @param quartzJob* @return boolean*/boolean saveAndScheduleJob(QuartzJob quartzJob);/*** 编辑定时任务* @param quartzJob* @return boolean* @throws SchedulerException*/boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException;/*** 删除定时任务* @param id* @return boolean*/boolean deleteAndStopJob(String id);/*** 恢复定时任务* @param quartzJob* @return*/boolean resumeJob(QuartzJob quartzJob);/*** 执行定时任务* @param quartzJob* @throws Exception*/void execute(QuartzJob quartzJob) throws Exception;/*** 暂停任务* @param quartzJob* @throws SchedulerException*/void pause(QuartzJob quartzJob);
}

8:ServiceImpl

package org.jeecg.modules.quartz.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.jeecg.modules.quartz.mapper.QuartzJobMapper;
import org.jeecg.modules.quartz.service.IQuartzJobService;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.Date;
import java.util.List;/*** @Description: 定时任务*/
@Slf4j
@Service
public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {@Autowiredprivate QuartzJobMapper quartzJobMapper;@Autowiredprivate Scheduler scheduler;/*** 立即执行的任务分组*/private static final String JOB_TEST_GROUP = "test_group";@Overridepublic List<QuartzJob> findByJobClassName(String jobClassName) {return quartzJobMapper.findByJobClassName(jobClassName);}/*** 保存&启动定时任务*/@Override@Transactional(rollbackFor = JeecgBootException.class)public boolean saveAndScheduleJob(QuartzJob quartzJob) {// DB设置修改quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);boolean success = this.save(quartzJob);if (success) {if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {// 定时器添加this.schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());}}return success;}/*** 恢复定时任务*/@Override@Transactional(rollbackFor = JeecgBootException.class)public boolean resumeJob(QuartzJob quartzJob) {schedulerDelete(quartzJob.getId());schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());quartzJob.setStatus(CommonConstant.STATUS_NORMAL);return this.updateById(quartzJob);}/*** 编辑&启停定时任务* @throws SchedulerException */@Override@Transactional(rollbackFor = JeecgBootException.class)public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {schedulerDelete(quartzJob.getId());schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());}else{scheduler.pauseJob(JobKey.jobKey(quartzJob.getId()));}return this.updateById(quartzJob);}/*** 删除&停止删除定时任务*/@Override@Transactional(rollbackFor = JeecgBootException.class)public boolean deleteAndStopJob(String id) {schedulerDelete(id);boolean ok = this.removeById(id);return ok;}@Overridepublic void execute(QuartzJob quartzJob) throws Exception {String jobName = quartzJob.getJobClassName().trim();Date startDate = new Date();String ymd = DateUtils.date2Str(startDate,DateUtils.yyyymmddhhmmss.get());String identity =  jobName + ymd;//3秒后执行 只执行一次// update-begin--author:sunjianlei ---- date:20210511--- for:定时任务立即执行,延迟3秒改成0.1秒-------startDate.setTime(startDate.getTime() + 100L);// update-end--author:sunjianlei ---- date:20210511--- for:定时任务立即执行,延迟3秒改成0.1秒-------// 定义一个TriggerSimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger().withIdentity(identity, JOB_TEST_GROUP).startAt(startDate).build();// 构建job信息JobDetail jobDetail = JobBuilder.newJob(getClass(jobName).getClass()).withIdentity(identity).usingJobData("parameter", quartzJob.getParameter()).build();// 将trigger和 jobDetail 加入这个调度scheduler.scheduleJob(jobDetail, trigger);// 启动schedulerscheduler.start();}@Override@Transactional(rollbackFor = JeecgBootException.class)public void pause(QuartzJob quartzJob){schedulerDelete(quartzJob.getId());quartzJob.setStatus(CommonConstant.STATUS_DISABLE);this.updateById(quartzJob);}/*** 添加定时任务** @param jobClassName* @param cronExpression* @param parameter*/private void schedulerAdd(String id, String jobClassName, String cronExpression, String parameter) {try {// 启动调度器scheduler.start();// 构建job信息JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(id).usingJobData("parameter", parameter).build();// 表达式调度构建器(即任务执行的时间)CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);// 按新的cronExpression表达式构建一个新的triggerCronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();scheduler.scheduleJob(jobDetail, trigger);} catch (SchedulerException e) {throw new JeecgBootException("创建定时任务失败", e);} catch (RuntimeException e) {throw new JeecgBootException(e.getMessage(), e);}catch (Exception e) {throw new JeecgBootException("后台找不到该类名:" + jobClassName, e);}}/*** 删除定时任务* * @param id*/private void schedulerDelete(String id) {try {scheduler.pauseTrigger(TriggerKey.triggerKey(id));scheduler.unscheduleJob(TriggerKey.triggerKey(id));scheduler.deleteJob(JobKey.jobKey(id));} catch (Exception e) {log.error(e.getMessage(), e);throw new JeecgBootException("删除定时任务失败");}}private static Job getClass(String classname) throws Exception {Class<?> class1 = Class.forName(classname);return (Job) class1.newInstance();}}

9:mapper

package org.jeecg.modules.quartz.mapper;import java.util.List;import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.quartz.entity.QuartzJob;import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** @Description: 定时任务*/
public interface QuartzJobMapper extends BaseMapper<QuartzJob> {/*** 根据jobClassName查询* @param jobClassName 任务类名* @return*/public List<QuartzJob> findByJobClassName(@Param("jobClassName") String jobClassName);}

10:mapper下的xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.quartz.mapper.QuartzJobMapper"><!-- 根据jobClassName查询 -->
<select id="findByJobClassName" resultType="org.jeecg.modules.quartz.entity.QuartzJob">select * from  sys_quartz_job  where job_class_name = #{jobClassName}</select>
</mapper>

11:实体类entity

package org.jeecg.modules.quartz.entity;import java.io.Serializable;import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;import lombok.Data;/*** @Description: 定时任务*/
@Data
@TableName("sys_quartz_job")
public class QuartzJob implements Serializable {private static final long serialVersionUID = 1L;/*** id*/@TableId(type = IdType.ASSIGN_ID)private java.lang.String id;/*** 创建人*/private java.lang.String createBy;/*** 创建时间*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")private java.util.Date createTime;/*** 删除状态*/private java.lang.Integer delFlag;/*** 修改人*/private java.lang.String updateBy;/*** 修改时间*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")private java.util.Date updateTime;/*** 任务类名*/@Excel(name = "任务类名", width = 40)private java.lang.String jobClassName;/*** cron表达式*/@Excel(name = "cron表达式", width = 30)private java.lang.String cronExpression;/*** 参数*/@Excel(name = "参数", width = 15)private java.lang.String parameter;/*** 描述*/@Excel(name = "描述", width = 40)private java.lang.String description;/*** 状态 0正常 -1停止*/@Excel(name = "状态", width = 15, dicCode = "quartz_status")@Dict(dicCode = "quartz_status")private java.lang.Integer status;}

12:简单的 Job 案例

如果调度器要执行任务,首先得要有一个任务相关的类

写了3个平常的案例,一个是不带参数同步的,一个是不带参数的,一个是带参数的

package org.jeecg.modules.quartz.job;import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.quartz.*;/*** @Description: 同步定时任务测试** 此处的同步是指 当定时任务的执行时间大于任务的时间间隔时* 会等待第一个任务执行完成才会走第二个任务*/
@PersistJobDataAfterExecution // 持久化JobDataMap里的数据,使下一个定时任务还能获取到这些值
@DisallowConcurrentExecution // 禁止并发多任务执行,所以永远只有一个任务在执行中
@Slf4j
public class AsyncJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {log.info(" --- 同步任务调度开始 --- " + " Job Execution key:"+jobExecutionContext.getJobDetail().getKey());try {//此处模拟任务执行时间 5秒  任务表达式配置为每秒执行一次:0/1 * * * * ? *Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}//测试发现 每5秒执行一次log.info(" --- 执行完毕,时间:"+DateUtils.now()+"---"  + " 线程名"+ Thread.currentThread().getName() );}}
package org.jeecg.modules.quartz.job;import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import lombok.extern.slf4j.Slf4j;/*** 示例不带参定时任务*/
@Slf4j
public class SampleJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());log.info(String.format(" Jeecg-Boot 普通定时任务 SampleJob !  时间:" + DateUtils.getTimestamp()));}
}
package org.jeecg.modules.quartz.job;import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import lombok.extern.slf4j.Slf4j;/*** 示例带参定时任务*/
@Slf4j
public class SampleParamJob implements Job {/*** 若参数变量名修改 QuartzJobController中也需对应修改*/private String parameter;public void setParameter(String parameter) {this.parameter = parameter;}@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());log.info( String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob !   时间:" + DateUtils.now(), this.parameter));}
}

13:使用postman测试带参


这是带参一次性任务,添加任务成功后,会在表qrtz_job_details生成一条待处理任务,处理完成后,会删除此记录,如果是循环任务会一直存在

** misfireThreshold表示如果容忍到时候还没处理任务的最大时间,如果超过时间就会变成报misfire

MisFire策略常量的定义在类CronTrigger中,列举如下:
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1
MISFIRE_INSTRUCTION_DO_NOTHING = 2
MISFIRE_INSTRUCTION_SMART_POLICY = 0
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1
根据JavaDoc介绍和官网文档分析,其对应执行策略如下:
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW:立即执行一次,然后按照Cron定义时间点执行
MISFIRE_INSTRUCTION_DO_NOTHING:什么都不做,等待Cron定义下次任务执行的时间点
MISFIRE_INSTRUCTION_SMART_POLICY:智能的策略,针对不同的Trigger执行不同,CronTrigger时为MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY:将所有错过的执行时间点全都补上,例如,任务15s执行一次,执行的任务错过了4分钟,则执行MisFire时,一次性执行4*(60/15)= 16次任务
影响misFire执行策略的另一个参数就是misfireThreshold

总结遇到的坑

** 开了两个服务,然后链接同一个数据库,如果定时任务到了,会随机在任意一个服务器运行的(遇到的坑是,一开始有时候执行有时候不执行,以为定时器框架问题,最好发现是开了两个服务的问题,还有注意不要开启集群,集群也是任务负载了)

** quartz定时器有时候执行有时候不执行的问题是,清空掉数据库表qrtz_scheduler_state的实例

** 对于临时的定时业务异常可以抛出JobExecutionException异常如下,可以一直重复运行,直到抛出异常,但是重启服务器就会失效

package org.jeecg.modules.quartz.job;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;/*** 示例不带参定时任务*/
@Slf4j
public class SampleJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());int a=0;try {a=a/a;} catch (Exception e) {log.error("执行任务出错了...");try {Thread.sleep(2000);} catch (InterruptedException e1) {e1.printStackTrace();}JobExecutionException e2 = new JobExecutionException(e);// this job will refire immediatelye2.setRefireImmediately(true);throw e2;}log.info(String.format(" Jeecg-Boot 普通定时任务 SampleJob !  时间:" + DateUtils.getTimestamp()));}
}

扩展 :@Scheduler定时任务执行默认是单线程实现并发执行问题

定时任务会根据任务执行线程池来执行,Spring中默认配置的任务执行线程池数量是1
通过在项目中增加以下配置,增加任务执行线程池数量来提升并发执行能力:

方法-1

@Configuration
public class ScheduledConfig {@Beanpublic TaskScheduler taskScheduler() {ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();taskScheduler.setPoolSize(10);return taskScheduler;}
}

方法-2

@Configuration
@EnableScheduling
@Slf4j
public class ScheduledConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {TaskScheduler scheduler = this.taskScheduler();scheduledTaskRegistrar.setTaskScheduler(scheduler);}@Bean(destroyMethod = "shutdown")public ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(10);scheduler.setThreadNamePrefix("task-");scheduler.setAwaitTerminationSeconds(60);scheduler.setWaitForTasksToCompleteOnShutdown(true);return scheduler;}

Spring Boot 集成Quartz相关推荐

  1. Spring Boot集成Quartz动态实现数据库任务

    1. Quartz简介 1.1. 什么是Quartz Quartz是一个开源的任务调度框架.作用是基于定时.定期的策略来执行任务. 它是OpenSymphony开源组织在Job scheduling领 ...

  2. Spring Boot集成Quartz注入Spring管理的类

    摘要: 在Spring Boot中使用Quartz时,在JOB中一般需要引用Spring管理的Bean,通过定义Job Factory实现自动注入. Spring有自己的Schedule定时任务,在S ...

  3. mysql的每隔1分钟定时_简单易用,spring boot集成quartz,实现分布式定时任务

    什么是quartz? Quartz是一个完全由 Java 编写的开源任务调度框架. 我们经常会遇到一些问题: 想每个月27号,提醒信用卡还款: 想每隔1小时,提醒一下,累了,站起来活动一下: 想每个月 ...

  4. spring boot集成Quartz实现定时任务

    简介 Quartz是一款功能强大的任务调度器,Quartz有两个比较核心的组件:Job 和 Trigger. Quartz的三个基本要素 Scheduler:调度器,所有的调度都是由它来控制. Tri ...

  5. Spring Boot 集成 Quartz

    1.美图 2.概述 在项⽬开发中,经常需要定时任务来帮助我们来做一些内容,⽐如定时派息.跑批对账.业务监控等.Spring Boot 体系中现在有两种⽅案可以选择,第⼀种是 Spring Boot 内 ...

  6. spring boot集成quartz scheduler

    工具.版本 开发工具:IntelliJ IDEA JDK:1.8 spring-boot:2.5.6(事例使用,可根据自己版本调整) maven:3.6.3 依赖jar <dependency& ...

  7. Spring Boot 集成SnakerFlow流程引擎,简介、功能列表、详细解读、扩展点分析

    文章目录 简介 功能列表 流程定义 任务参与者 参与者设置 动态添加.删除参与者 组支持 详细解读 Spring Boot集成 表定义 表详细说明: 字段详细说明: 常见操作 常规API 综合查询 模 ...

  8. Spring boot2集成quartz动态任务管理+Web UI

    Dynamic Quartz ​ 最近在公司实习,发现公司有一套spring+Quartz的动态任务管理系统.可以使用Web界面进行任务动态的创建.删除.停止.运行和修改.刚好最近在学习spring ...

  9. Spring Boot集成Swagger导入YApi@无界编程

    接口APi开发现状 现在开发接口都要在类似YApi上写文档,这样方便不同的团队之间协作,同步更新接口,提高效率. 但是如果接口很多,你一个个手工在YApi去录入无疑效率很低. 如果是使用Spring ...

最新文章

  1. c语言入口及出口参数说明,麻烦帮忙指出一下这个函数的入口参数和出口参数呀!...
  2. How does ABAP check table work
  3. JSON 解析的两种方法
  4. 为什么阿里内部不允许用Executors创建线程池?
  5. iOS 开发之 - iOS6适配 - 导航栏按钮透明方法
  6. leetcode力扣647. 回文子串
  7. InDesign教程,如何更改字体和字体大小?
  8. 论文笔记_CV_AD_Visual Perception for Autonomous Driving
  9. KeyShot中该怎么添加反射地平面
  10. relative会脱离文档流吗_抖音投放你会吗?选Feed流还是Dou+?
  11. python中的statistics_详解python statistics模块及函数用法
  12. 【力扣 912】十大排序算法
  13. 获取GooglePlay下载来源广告数据统计接入
  14. K.论演员的自我修养---组合数的运用路径计数
  15. 必背C语言算法 C语言小写转大写
  16. 怎样提取PDF文件其中一页
  17. linux pppd源码下载_Linux中的pppd
  18. fama french-3 模型个人理解
  19. Cyberpunk!特斯拉发布皮卡,造型雷翻众人
  20. GPS中的空间坐标系

热门文章

  1. AntV-G6:画直角树形图
  2. ReactiveX 操作符
  3. 流传已久的荒唐故事(一)-铅笔与太空笔
  4. Windows下Firefox打开网页出现:此网址已被限制-此网址使用了一个通常用于网络浏览以外目的的端口-firefox取消端口限制方法
  5. 浪潮速面(8.24)已offer(9.8)
  6. macOS BigSur Parallel Desktop 16 Win10 虚拟机无法连接网络
  7. 无盘win2008服务器,win2008无盘服务器配置
  8. Python 简单爬虫(mm图)
  9. 啃完这些资料,我拿到了腾讯,爱奇艺,Kotlin从入门到进阶实战
  10. 华为HCIP—Datacom(821新增)