Quartz是什么?Quartz是一个强大任务调度框架,可以用来干嘛?如一个OA系统需要在每周五9点自动生成数据报表,或者想每月10号自动还款,又或者每周给暗恋的女生定时发送邮件等等。下面介绍Quartz的三个核心概念(job,Trigger,Scheduler)。
导入依赖:
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-quartzartifactId>
- dependency>
1,任务job
job就是你想实现的任务类,每一个job必须实现org.quartz.job接口,且只需实现接口定义的execute()方法。
Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似jdk提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑。
例如:
- import org.quartz.Job;
- import org.quartz.JobDataMap;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- /**
- * @create: 2022-09-17
- **/
- public class ScheduleExportJobDTO implements Job {
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- try {
- JobDataMap jobDataMap = context.getMergedJobDataMap();
- Integer documentId = jobDataMap.getInt("documentId");
- logger.info("执行导出任务,documentId:{}", documentId);
-
- //这个下面调用的就是你想执行的任务方法,我这里是调用一个类里面的导出任务。
- ICEDEvidenceDocumentExportScheduleManager exportScheduleManager = SpringUtils.getBean(ICEDEvidenceDocumentExportScheduleManager.class);
- exportScheduleManager.scheduleExport(documentId);
-
-
- }catch (Exception e){
- logger.info("执行导出任务失败, msg:{}", e.getMessage());
- context.setResult(null);
- throw new JobExecutionException("执行导出任务失败",e);
- }
- }
-
- }
JobDetall :使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建。实例在Quartz中的生命周期,每次调度器执行job时它在调用execute方法前,会创建一个新的job实例,当调用完成后,关联
的job对象实例会被是释放,释放的实例会被垃圾回收机制回收。
例如:
- JobDetail jobDetail=JobBuilder.newJob(ScheduleExportJobDTO .class)//加载任务类,与任务类绑定
- .withIdentity("job", "group")//参数1:任务名称,参数2:组名称
- .usingJobData("dataMap", "message")//可以设置JobDataMap,获取存取信息
- .build();//创建实例
2,触发器Trigger
Trigger 为你执行任务的触发器,比如你想每天定时1点发送邮件,Trigger将会设置1点执行该任务。
Trigger主要包含两种:SimpleTrigger和CronTriggerr。
Trgger触发器 :Trigger对象是用于触发执行Job的,当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件,比如每秒执行一次。
例如:
- //2,触发器,Quartz里有多个触发器,最常用的是SimpleTrigger,CronTrigger;
- SimpleTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group")
- .withSchedule(SimpleScheduleBuilder.simpleSchedule()//属性有开始时间,结束时间,重复次数,重复时间间隔
- .repeatSecondlyForTotalCount(5, 1))//参数1:count,参数2:second.每一秒重复执行,总共执行3遍
- // .startNow()//立刻执行
- .startAt(new Date())//设置任务开始时间
- .endAt(date)//设置任务结束时间
- .build();
-
- //触发器
- CronTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()//立刻执行
- .withSchedule(CronScheduleBuilder.cronSchedule("0 * * * * ?"))//表示每次0秒时候执行。
- .build();
3,调度器Scheduler
Scheduler是任务的调度器,会将任务job和触发器TRigger结合,负责基于Trigger设定的时间执行job。
- // 方法之二:从工厂中获取默认的
- Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
- scheduler.scheduleJob(jobDetail,trigger);//关联两者
- //方法之一
- @Autowired
- private Scheduler scheduler;
-
- scheduler.scheduleJob(jobDetail, trigger);
4.JobDataMap :可包含数据对象,在job实例执行的是好,可使用包含的数据;JobDataMap是java Map接口的实现,增加了一些存取基本类型方法。
案例提供:
需求关于对导出文档这个任务实现定时策略。
关键代码:包含二个类 1.job类,实现导出任务的任务类,只在execute方法中实现了导出任务。
2.ScheduleManager管理类,其中有addJob-增加定时导出文档任务,startJob-恢复定时导出文档任务(若以往没有该任务则新增定时导出任务),stopJob-停止定时导出文档任务,getScheduler-获取当前正在执行的定时导出文档任务。
1.job类
- import org.quartz.Job;
- import org.quartz.JobDataMap;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- /**
- * @create: 2022-09-17
- **/
- public class ScheduleExportJobDTO implements Job {
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- try {
- JobDataMap jobDataMap = context.getMergedJobDataMap();
- Integer documentId = jobDataMap.getInt("documentId");
- logger.info("执行导出任务,documentId:{}", documentId);
-
- //这个下面调用的就是你想执行的任务方法,我这里是调用一个类里面的导出任务。
- ICEDEvidenceDocumentExportScheduleManager exportScheduleManager = SpringUtils.getBean(ICEDEvidenceDocumentExportScheduleManager.class);
- exportScheduleManager.scheduleExport(documentId);
-
-
- }catch (Exception e){
- logger.info("执行导出任务失败, msg:{}", e.getMessage());
- context.setResult(null);
- throw new JobExecutionException("执行导出任务失败",e);
- }
- }
-
- }
2.ScheduleManager管理类
- import org.quartz.*;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
-
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
-
- /**
- * @create: 2022-09-18
- **/
- @Component
- public class ICEDEvidenceDocumentExportScheduleManager {
-
- @Autowired
- private ICEDEvidenceDocumentExportScheduleMapper exportScheduleMapper;
- @Autowired
- private ICEDEvidenceDocumentManager documentManager;
- @Autowired
- private ICEDEvidenceDocumentExportManager documentExportManager;
- @Autowired
- private ICEDEvidenceDocumentStructureMapper documentStructureMapper;
- @Autowired
- private ICEDEvidenceDocumentOperationLogService operationLogService;
- @Autowired
- private ICEDEvidenceDocumentService documentService;
- @Autowired
- private TokenService tokenService;
- @Autowired
- private Scheduler scheduler;
-
- private final CopyOptions copyOptions = CopyOptions.create(null, true);
-
- private static final String JOB_NAME_PREFIX = "export-job-";
-
- private static final String TRIGGER_NAME_PREFIX = "export-trigger-";
-
- private static final Integer ADMIN_USER_ID = 1;
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- public void addJob(Integer documentId, String cronExpression) throws SchedulerException {
- JobKey jobKey = getJobKey(documentId);
- logger.info("创建调度任务 jobKey:{}, cronExpression:{}", jobKey, cronExpression);
- JobDetail jobDetail = JobBuilder.newJob(ScheduleExportJobDTO.class)
- .withIdentity(jobKey)
- .usingJobData("documentId", documentId)
- .build();
- CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(documentId))
- .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
- .build();
- scheduler.scheduleJob(jobDetail, trigger);
- }
-
- public void startJob(Integer documentId, String cronExpression) throws SchedulerException {
- JobKey jobKey = getJobKey(documentId);
- if (scheduler.checkExists(jobKey)){
- logger.info("恢复调度任务 jobKey:{}", jobKey);
- scheduler.resumeJob(jobKey);
- }else {
- logger.info("创建调度任务 jobKey:{}, cronExpression:{}", jobKey, cronExpression);
- JobDetail jobDetail = JobBuilder.newJob(ScheduleExportJobDTO.class)
- .withIdentity(getJobKey(documentId))
- .usingJobData("documentId", documentId)
- .build();
- CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(documentId))
- .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
- .build();
- scheduler.scheduleJob(jobDetail, trigger);
- }
- }
-
- public void stopJob(Integer documentId) throws SchedulerException {
- JobKey jobKey = getJobKey(documentId);
- logger.info("停止调度任务 jobKey:{}", jobKey);
- scheduler.pauseJob(jobKey);
- }
-
- private JobKey getJobKey(Integer documentId){
- return JobKey.jobKey(JOB_NAME_PREFIX + documentId);
- }
-
- private TriggerKey getTriggerKey(Integer documentId){
- return TriggerKey.triggerKey(TRIGGER_NAME_PREFIX + documentId);
- }
-
- public Integer saveExportSchedule(ICEDEvidenceDocumentExportScheduleReqDTO exportScheduleReqDTO) {
- Integer loginUserId = getLoginUserId();
- Integer loginUserDeptId = getLoginUserDeptId();
- Date now = new Date();
-
- ICEDEvidenceDocumentExportSchedule exportSchedule = new ICEDEvidenceDocumentExportSchedule();
- BeanUtil.copyProperties(exportScheduleReqDTO, exportSchedule, copyOptions);
- exportSchedule.setOper(loginUserId);
- exportSchedule.setUpdator(loginUserId);
- exportSchedule.setOpTime(now);
- exportSchedule.setUpdateTime(now);
- exportSchedule.setDeptId(loginUserDeptId);
- exportScheduleMapper.insertSelective(exportSchedule);
- return exportSchedule.getId();
- }
-
- public void scheduleExport(Integer documentId){
- ICEvidenceDocument document = documentManager.getEvidenceDocument(documentId);
-
- List
documentStructureList = documentStructureMapper.selectChapterDocumentStructure(documentId); - List
dataDTOList = new ArrayList<>(); - for (ICEDEvidenceDocumentStructure documentStructure : documentStructureList) {
- //dataTree 中已经进行权限过滤
- dataDTOList.add(documentService.dataTree(documentStructure.getId()));
- }
- logger.info("查询导出文档数据完成");
- //记录操作日志
- Integer operationLogId = operationLogService.recordLogBeforeOperation(documentId,
- ICEDEvidenceDocumentOperationType.EXPORT, dataDTOList, null);
- logger.info("记录导出文档操作日志,operationLogId:{}, status: {}", operationLogId, ICEDEvidenceDocumentOperationStatus.getStatusMeaning(ICEDEvidenceDocumentOperationStatus.OPERATING));
- documentExportManager.scheduleExport(document.getTemplateId(), dataDTOList, operationLogId, ADMIN_USER_ID);
- }
-
-
- public Integer getLoginUserId(){
- LoginUser loginUser = tokenService.getLoginUser();
- if (loginUser == null){
- throw new CheckedException("获取当前登录用户失败");
- }
- return Math.toIntExact(loginUser.getUserid());
- }
-
- public Integer getLoginUserDeptId(){
- LoginUser loginUser = tokenService.getLoginUser();
- if (loginUser == null){
- throw new CheckedException("获取当前登录用户失败");
- }
- SysUser sysUser = loginUser.getSysUser();
- if (sysUser == null){
- throw new CheckedException("获取当前登录用户信息失败");
- }
- return Math.toIntExact(sysUser.getDeptId());
- }
-
-
- public String getScheduler() throws SchedulerException {
- List
currentlyExecutingJobList = scheduler.getCurrentlyExecutingJobs(); - return JSON.toJSONString(currentlyExecutingJobList);
- }
- }