天天看點

quartz 動态添加job_SpringBoot內建Quartz 2.3.1動态管理定時任務,這個工具類絕對解決你的所有需求!...

最近在做一個定時相關的功能,選擇使用quartz來完成。這個過程中自己封裝了一個QuartzUtil工具類,并且一步步完善,填了很多坑。相比于其他類似的文章,個人感覺我寫的這個工具類還算是比較完善的一個了。

我也寫了一個簡單的demo項目,用來幫助你更好的了解,公衆号回複【github】擷取項目github位址,該項目我會一直保持更新。

主要實作功能如下:

  • 基于quartz2.3.1實作動态管理定時任務。
  • 使用swagger實作接口文檔。
  • 前後端統一使用JSON格式互動。

當然也可以直接帶走這個工具類,類中使用了我自定義的一個異常類和一個枚舉類,都一起放在下面了。個人并未配置quartz.properties,使用時隻需添加quartz依賴,然後将quartzUtil和兩個相關的類放到項目中即可。

一、項目swagger文檔

quartz 動态添加job_SpringBoot內建Quartz 2.3.1動态管理定時任務,這個工具類絕對解決你的所有需求!...

二、項目Maven依賴

很巧都是基于2.3.1版本。

(1) springboot版本

org.springframework.boot  spring-boot-starter-parent  2.3.1.RELEASE  
           

(2) quartz依賴

org.quartz-scheduler  quartz  2.3.1
           

三、quartz工具類

在QuartzUtil中用到了我自定義的異常類CustomException和枚舉類Code。

(1) CustomException類

/** * @author frost2 * @date 2020-9-23 17:23:38 */@[email protected]@Setterpublic class CustomException extends RuntimeException {    public CustomException(int code, String msg) {        this.code = code;        this.msg = msg;    }    public CustomException(Code code) {        this.code = code.getCode();        this.msg = code.getMsg();    }    private int code;    private String msg;}
           

(2) Code類

為了不讓篇幅太長,我隻保留QuartzUtil中用到的狀态碼。

/** * @author frost2 * @date 2020-9-23 17:23:43 */@[email protected] enum Code {    PARAM_FORMAT_ERROR(2004, "參數異常"),    EXECUTION_ERROR(6002, "接口執行失敗");    //枚舉的屬性字段必須是私有且不可變    private final int code;    private final String msg;    Code(int code, String msg) {        this.code = code;        this.msg = msg;    }}
           

(3) QuartzUtil 類

/** * @author frost2 * @date 2020-9-17 15:38:43 */public class QuartzUtil {    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();    private static Scheduler scheduler;    static {        try {            scheduler = schedulerFactory.getScheduler();        } catch (SchedulerException e) {            throw new CustomException(Code.EXECUTION_ERROR);        }    }    /**     * 傳入:任務名稱、觸發器名稱、任務描述、要執行的任務類、cron表達式建立定時任務,     * 傳回是否建立成功     *      * 注:     * 在建立任務時未設定jobGroup和triggerGroup,Job建立後其均為預設值:DEFAULT,     * 是以新建立的任務的jobName和triggerName,均不能與之前任務的重複.     *     * @param jobName     任務名     * @param triggerName 觸發器名     * @param description 對該任務的秒數(非必須)     * @param jobClass    要執行的任務     * @param cron        cron表達式     * @return true:建立Job成功,false:建立Job失敗     */    public static  boolean addJob(String jobName, String triggerName, String description,                                                 Class jobClass, String cron) {        try {            JobDetail jobDetail = JobBuilder.newJob(jobClass)                    .withIdentity(jobName)                    .withDescription(description)//                    .usingJobData("param1", "将參數")//                    .usingJobData("param2", "傳遞到JOB任務中使用")                    .build();            CronTrigger cronTrigger = TriggerBuilder.newTrigger()                    .withIdentity(triggerName)                    .startNow()                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))                    .build();            scheduler.scheduleJob(jobDetail, cronTrigger);            if (!scheduler.isShutdown()) {                scheduler.start();            }            return scheduler.isStarted();        } catch (Exception e) {            throw new CustomException(Code.EXECUTION_ERROR);        }    }    /**     * 修改一個任務的觸發時間     *     * @param jobName     任務名稱     * @param triggerName 觸發器名     * @param cron        cron表達式     * @return true:修改Job成功,false:修改Job失敗     */    public static Boolean rescheduleJob(String jobName, String triggerName, String cron) {        try {            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);            if (trigger == null) {                return false;            }            checkJobNameAndTriggerName(jobName, trigger);            Date latestFireTime = new Date();            if (!trigger.getCronExpression().equalsIgnoreCase(cron)) {                trigger = TriggerBuilder.newTrigger()                        .withIdentity(triggerName)                        .startNow()                        .withSchedule(CronScheduleBuilder.cronSchedule(cron))                        .build();                //rescheduleJob()執行成功傳回最近一次執行的時間,如果失敗傳回null                latestFireTime = scheduler.rescheduleJob(triggerKey, trigger);            }            return null != latestFireTime;        } catch (SchedulerException e) {            throw new CustomException(Code.EXECUTION_ERROR);        }    }    /**     * 根據jobName和triggerName删除該JOB     *     * @param jobName     任務名稱     * @param triggerName 觸發器名     * @return true:删除Job成功,false:删除Job失敗     */    public static boolean removeJob(String jobName, String triggerName) {        boolean flag;        try {            Trigger trigger = scheduler.getTrigger(new TriggerKey(triggerName));            if (null == trigger) {                return false;            }            checkJobNameAndTriggerName(jobName, trigger);            TriggerKey triggerKey = trigger.getKey();            scheduler.pauseTrigger(triggerKey);            flag = scheduler.unscheduleJob(triggerKey);            //删除trigger之後無需在删除job,因為相關的job如果不是持久的,則将被自動删除。下面這種寫法flag=false//            if (flag) {//                flag = scheduler.deleteJob(JobKey.jobKey(jobName));//            }        } catch (SchedulerException e) {            throw new CustomException(Code.EXECUTION_ERROR);        }        return flag;    }    /**     * 根據jobName和triggerName查詢該JOB     *     * @param jobName     任務名稱     * @param triggerName 觸發器名     * @return 該Job相關資訊[詳見getJobInfo方法]     */    public static HashMap getJob(String jobName, String triggerName) {        try {            JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobName));            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(new TriggerKey(triggerName));            if (null == jobDetail || null == trigger) {                return new HashMap<>();            }            checkJobNameAndTriggerName(jobName, trigger);            return getJobInfo(jobDetail, trigger);        } catch (SchedulerException e) {            throw new CustomException(Code.EXECUTION_ERROR);        }    }    /**     * 查詢所有正在執行的JOB     *     * @return 該Job相關資訊[詳見getJobInfo方法]     */    public static List> getJobs() {        List> list = new ArrayList<>();        try {            List triggerGroupNames = scheduler.getTriggerGroupNames();            for (String groupName : triggerGroupNames) {                GroupMatcher groupMatcher = GroupMatcher.groupEquals(groupName);                //擷取所有的triggerKey                Set triggerKeySet = scheduler.getTriggerKeys(groupMatcher);                for (TriggerKey triggerKey : triggerKeySet) {                    //擷取CronTrigger                    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);                    //擷取trigger對應的JobDetail                    JobDetail jobDetail = scheduler.getJobDetail(trigger.getJobKey());                    list.add(getJobInfo(jobDetail, trigger));                }            }        } catch (SchedulerException e) {            throw new CustomException(Code.EXECUTION_ERROR);        }        return list;    }    /**     * @param cron cron表達式     * @return 最近5次的執行時間     */    public static List getRecentTriggerTime(String cron) {        List list = new ArrayList<>();        try {            CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();            cronTriggerImpl.setCronExpression(cron);            List dateList = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 5);            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            dateList.forEach(date -> list.add(dateFormat.format(date)));        } catch (ParseException e) {            throw new CustomException(Code.EXECUTION_ERROR);        }        return list;    }    /**     * 校驗cron表達式是否正确     *     * @param cronExpression cron表達式     * @return true:正确,false:不正确     */    @SuppressWarnings("all")    public static boolean checkCronExpression(String cronExpression) {        return CronExpression.isValidExpression(cronExpression);    }    /**     * 擷取該Job對應的相關資訊     */    private static HashMap getJobInfo(JobDetail jobDetail, CronTrigger trigger) {        HashMap map = new HashMap<>();        map.put("jobName", jobDetail.getKey().getName());        map.put("jobGroup", jobDetail.getKey().getGroup());        map.put("corn", trigger.getCronExpression());        map.put("triggerName", trigger.getKey().getName());        map.put("description", jobDetail.getDescription());        return map;    }    /**     * 校驗jobName和triggerName是否比對     * 如不比對抛出自定義異常     */    private static void checkJobNameAndTriggerName(String jobName, Trigger trigger) {        String name = trigger.getJobKey().getName();        if (!name.equals(jobName)) {            throw new CustomException(Code.PARAM_FORMAT_ERROR.getCode(), "jobName與triggerName不比對");        }    }}
           

三、關注回複【有驚喜】

quartz 動态添加job_SpringBoot內建Quartz 2.3.1動态管理定時任務,這個工具類絕對解決你的所有需求!...