All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diboot.scheduler.service.impl.QuartzSchedulerServiceImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2015-2021, www.dibo.ltd ([email protected]).
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.diboot.scheduler.service.impl; import com.diboot.core.exception.BusinessException; import com.diboot.core.util.BeanUtils; import com.diboot.core.util.ContextHolder; import com.diboot.core.util.JSON; import com.diboot.core.util.V; import com.diboot.core.vo.Status; import com.diboot.scheduler.annotation.CollectThisJob; import com.diboot.scheduler.entity.ScheduleJob; import com.diboot.scheduler.service.QuartzSchedulerService; import lombok.extern.slf4j.Slf4j; import org.quartz.*; import org.quartz.impl.matchers.GroupMatcher; import org.springframework.beans.factory.annotation.Autowired; import jakarta.annotation.PostConstruct; import java.util.*; /** * 调度任务quartz实现 * * @author [email protected] * @version v2.2 * @date 2020/11/27 */ @Slf4j public class QuartzSchedulerServiceImpl implements QuartzSchedulerService { /** * 任务初始化策略 */ enum INIT_STRATEGY { // 周期执行 DO_NOTHING, //立即执行一次,并周期执行 FIRE_AND_PROCEED, //超期立即执行,并周期执行 IGNORE_MISFIRES } // 任务的缓存 public static final List> CACHE_JOB = new ArrayList<>(); @Autowired private Scheduler scheduler; @PostConstruct public void startScheduler() { try { scheduler.start(); } catch (SchedulerException e) { log.error("定时任务scheduler初始化异常,请检查!", e); } } /** * 获取当前系统中的所有定时任务 * * @return */ @Override public List> loadAllJobs() { if (V.notEmpty(CACHE_JOB)) { return CACHE_JOB; } // 获取所有被com.diboot.scheduler.job.anno.CollectThisJob注解的job List annoJobList = ContextHolder.getBeansByAnnotation(CollectThisJob.class); if (V.notEmpty(annoJobList)) { List> result = loadJobs(annoJobList); CACHE_JOB.addAll(result); } return CACHE_JOB; } /** * 加载job定义 * * @param annoJobList * @return */ private List> loadJobs(List annoJobList) { List> result = new ArrayList<>(); for (Object job : annoJobList) { if (!(job instanceof Job)) { log.warn("无效的job任务: {}", job.getClass()); continue; } Map temp = new HashMap<>(8); Class targetClass = BeanUtils.getTargetClass(job); CollectThisJob annotation = targetClass.getAnnotation(CollectThisJob.class); temp.put("jobKey", targetClass.getSimpleName()); temp.put("jobCron", annotation.cron()); temp.put("jobName", annotation.name()); temp.put("jobClass", targetClass); Class paramClass = annotation.paramClass(); String paramJsonExample = annotation.paramJson(); if (V.isEmpty(paramJsonExample) && !Object.class.getTypeName().equals(paramClass.getTypeName())) { try { paramJsonExample = JSON.stringify(paramClass.newInstance()); } catch (Exception e) { log.error("job任务:{}, Scheduled#paramClass参数任务无效,建议使用Scheduled#paramJson参数替换!", job.getClass()); } } temp.put("paramJsonExample", paramJsonExample); result.add(temp); } return result; } /** * 获取调度器重的所有任务列表 * * @return */ @Override public List> loadJobsInScheduler() { List> jobList = null; try { Set jobKeys = scheduler.getJobKeys(GroupMatcher.anyJobGroup()); 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) { log.error("加载全部Job异常", e); } return jobList; } /** * 添加 cron表达式job * * @param job */ @Override public void addJob(ScheduleJob job) { TriggerKey triggerKey = TriggerKey.triggerKey(job.getId().toString()); // 构建参数 JobDetail jobDetail = JobBuilder.newJob(getJobClass(job.getJobKey())).withIdentity(job.getId().toString()).build(); if (V.notEmpty(job.getParamJson())) { Map jsonData = JSON.toMap(job.getParamJson()); jobDetail.getJobDataMap().putAll(jsonData); } try { // 表达式调度构建器 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCron()); // 设置定时任务初始化策略 if (INIT_STRATEGY.FIRE_AND_PROCEED.name().equals(job.getInitStrategy())) { cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed(); } else if (INIT_STRATEGY.IGNORE_MISFIRES.name().equals(job.getInitStrategy())) { cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires(); } // 定时任务 Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); } catch (Exception e) { log.error("添加定时任务异常", e); throw new BusinessException(Status.FAIL_OPERATION, e, "exception.business.quartzSchedulerService.addTaskFailed"); } } /** * 添加一个立即执行一次的job * * @param job */ @Override public void addJobExecuteOnce(ScheduleJob job) { TriggerKey triggerKey = TriggerKey.triggerKey(job.getId().toString()); // 构建参数 JobDetail jobDetail = JobBuilder.newJob(getJobClass(job.getJobKey())).withIdentity(job.getId().toString()).build(); if (V.notEmpty(job.getParamJson())) { Map jsonData = JSON.toMap(job.getParamJson()); jobDetail.getJobDataMap().putAll(jsonData); } try { // 立即执行,且只执行一次 Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0)).build(); scheduler.scheduleJob(jobDetail, trigger); } catch (Exception e) { log.error("添加定时任务异常", e); throw new BusinessException(Status.FAIL_OPERATION, e, "exception.business.quartzSchedulerService.addTaskFailed"); } } /** * 立即执行job * * @param jobId */ @Override public void runJob(String jobId) { try { scheduler.triggerJob(JobKey.jobKey(jobId.toString())); } catch (SchedulerException e) { log.error("运行job异常", e); } } /** * 暂停job * * @param jobId */ @Override public void pauseJob(String jobId) { try { scheduler.pauseJob(JobKey.jobKey(jobId.toString())); } catch (Exception e) { log.error("暂停job异常", e); } } /** * 恢复job * * @param jobId */ @Override public void resumeJob(String jobId) { try { scheduler.resumeJob(JobKey.jobKey(jobId.toString())); } catch (SchedulerException e) { log.error("恢复job异常", e); } } /** * 删除job * * @param jobId */ @Override public void deleteJob(String jobId) { TriggerKey triggerKey = TriggerKey.triggerKey(jobId.toString()); try { scheduler.pauseTrigger(triggerKey); scheduler.unscheduleJob(triggerKey); scheduler.deleteJob(JobKey.jobKey(jobId.toString())); } catch (Exception e) { log.error("删除job异常", e); } } /** * 更新一个job的cron表达式 * * @param jobId * @param cron 定时表达式 */ @Override public void updateJobCron(String jobId, String cron) { TriggerKey triggerKey = TriggerKey.triggerKey(jobId.toString()); try { Trigger trigger = scheduler.getTrigger(triggerKey); CronTrigger cronTrigger = (CronTrigger) trigger; if (!cronTrigger.getCronExpression().equals(cron)) { cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(cron)).startNow().build(); scheduler.rescheduleJob(triggerKey, cronTrigger); } } catch (Exception e) { log.error("更新job的cron定时表达式异常", e); } } /** * 判断是否存在job * * @return */ @Override public boolean existJob(String jobId) { TriggerKey triggerKey = TriggerKey.triggerKey(jobId.toString()); try { Trigger trigger = scheduler.getTrigger(triggerKey); return V.notEmpty(trigger); } catch (SchedulerException e) { e.printStackTrace(); } return false; } /** * 获取JobClass * * @param jobKey * @return jobClass */ public Class getJobClass(String jobKey) { try { Class jobClass = loadAllJobs().stream() .filter(e -> String.valueOf(e.get("jobKey")).equals(jobKey)) .map(e -> (Class) e.get("jobClass")) .findAny() .orElse(null); if (jobClass == null) { throw new BusinessException(Status.FAIL_INVALID_PARAM, "exception.business.quartzSchedulerService.illegalTask", jobKey); } return jobClass; } catch (Exception e) { log.error("定时任务加载失败", e); throw new BusinessException(Status.FAIL_OPERATION, "exception.business.quartzSchedulerService.loadFailed"); } } }