SpringBoot Quartz 总结(动态任务,Corn表达式)

我就直接粘贴代码了,后台包括了jar包的引入,任务管理类(可以动态的创建任务,删除任务,暂停任务等等),解决Quartz不能引入bean的问题,SpringBoot初始化启动Quartz等等. 关于创建Job类是写一个类实现Job接口并且实现Job中的execute方法.这个可以网上去搜我就不粘贴了.

前台涉及到了填写Corn表达式,由于Corn表达式即使相对于后台人员来说也是相当复杂的,更别说是运维人员,所以需求是Corn表达式的生成是用程序生成.我描述我实现的方法

1.Quartz后台总结

<dependency> 
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
/**
 * 任务管理类
 *
 * @author ZhuPengWei
 * @date 2018/5/17 10:57
 */
@Component
@Slf4j
public class QuartzManager {

    @Autowired
    private Scheduler sched;
    /**
     * 任务组名
     */
    private static String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";
    /**
     * 触发器组名
     */
    private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";

    /**
     * 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
     *
     * @param jobName 任务名
     * @param cls     任务
     * @param time    任务触发时间( corn 表达式)
     */
    public void addJob(String jobName, Class cls, String time, Object params) {
        try {
            JobDetail jobDetail = new JobDetailImpl(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类
            jobDetail.getJobDataMap().put("params", params);
            // 触发器
            CronTriggerImpl trigger = new CronTriggerImpl(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组
            //trigger.wait();
            trigger.setCronExpression(time);// 触发器时间设定
            sched.scheduleJob(jobDetail, trigger);
            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 修改一个任务的触发时间(使用默认的任务组名 , 触发器名 , 触发器组名)
     *
     * @param jobName 任务名称
     * @param time    任务触发时间( corn 表达式)
     */
    public void modifyJobTime(String jobName, String time) {
        try {
            CronTriggerImpl trigger = (CronTriggerImpl) sched.getTrigger(new TriggerKey(jobName, TRIGGER_GROUP_NAME));
            if (trigger == null) {
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                JobDetail jobDetail = sched.getJobDetail(new JobKey(jobName, JOB_GROUP_NAME));
                Class objJobClass = jobDetail.getJobClass();
                removeJob(jobName);
                addJob(jobName, objJobClass, time, jobDetail.getJobDataMap().get("params"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改一个任务的触发以及触发内容(使用默认的任务组名 , 触发器名 , 触发器组名)
     *
     * @param jobName  任务名称
     * @param jobValue 内容
     * @param time     任务触发时间( corn 表达式)
     */
    public void modifyJobTime(String jobName, String jobValue, String time) {
        try {
            CronTriggerImpl trigger = (CronTriggerImpl) sched.getTrigger(new TriggerKey(jobName, TRIGGER_GROUP_NAME));
            if (trigger == null) {
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                JobDetail jobDetail = sched.getJobDetail(new JobKey(jobName, JOB_GROUP_NAME));
                Class objJobClass = jobDetail.getJobClass();
                removeJob(jobName);
                addJob(jobName, objJobClass, time, jobValue);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 移除一个任务(使用默认的任务组名 , 触发器名 , 触发器组名)
     *
     * @param jobName 任务名称
     */
    public void removeJob(String jobName) {
        try {
            sched.pauseTrigger(new TriggerKey(jobName, TRIGGER_GROUP_NAME));// 停止触发器
            sched.unscheduleJob(new TriggerKey(jobName, TRIGGER_GROUP_NAME));// 移除触发器
            sched.deleteJob(new JobKey(jobName, JOB_GROUP_NAME));// 删除任务
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 移除多个任务(使用默认的任务组名 , 触发器名 , 触发器组名)
     *
     * @param jobNames 任务名称集合
     */
    public void removeJobs(List<String> jobNames) {
        for (String jobName : jobNames) {
            removeJob(jobName);
            log.info("移除工作任务:{}", jobName);
        }
    }


    /**
     * 启动所有定时任务
     */
    public void startJobs() {
        try {
            sched.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 关闭所有定时任务
     */
    public void shutdownJobs() {
        try {
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
/**
 * 解决quartz的job中使用autowired注解注入的对象为空,
 *
 * @author ZhuPengWei
 * @date 2018/5/22 15:52
 */
public class JobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}
/**
 * 解决quartz的job中使用autowired注解注入的对象为空,
 *
 * @author ZhuPengWei
 * @date 2018/5/22 15:52
 */
@Configuration
public class JobFactoryConfig {

    @Bean
    public JobFactory jobFactory() {
        return new JobFactory();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(jobFactory());
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        return schedulerFactoryBean;
    }
}

/**
 * CommandLineRunner 接口的 Component 会在所有 SpringBeans都初始化之后
 * SpringApplication.run()之前执行
 * 初始化定时任务
 *
 * @author ZhuPengWei
 * @date 2018/5/19 17:05
 */
@Component
@Slf4j
public class TimedTaskWhenApplicationStartUp implements CommandLineRunner {

    @Autowired
    private MessageActionMasterJpaRepository messageActionMasterJpaRepository;

    @Autowired
    private TimedTaskSendService timedTaskSendService;

    @Override
    public void run(String... args) {
        try {
            // 查询quartz表达式不是null并且发送消息的数据
            List<MessageActionMaster> byQuartzExpressionIsNotNullAndIsSendMessageTrue = messageActionMasterJpaRepository.findByQuartzExpressionIsNotNullAndIsSendMessageTrue();
            // 批量新增任务
            timedTaskSendService.batchAddTask(byQuartzExpressionIsNotNullAndIsSendMessageTrue);
            log.info("-------------------定时任务初始化完毕-------------------");
        } catch (Exception e) {
            log.error("启动时候定时任务出现异常,{},{}", e, e.fillInStackTrace());
        }

    }
}

2.前端总结

对于一个后台人员来说 手动用Jquery实现页面生成Corn表达式是十分困难的,我在百度和谷歌上搜索了大量的前端Corn插件 ,要不界面是在太丑,无法集成到后台的项目中,要不生成的Corn表达式居然是错误的.是在是相当的为难.
所幸运的是我在github上找到了一个开源项目 并且集成到了我的后台项目之中.

我首先粘贴下这个项目的地址:

https://embed.plnkr.co/LCNjHr1s1rlr1FSXesMg/

我实现的效果图如下:

image

image

image

说明和描述的功能是我自己加入的 我粘贴一下描述的具体代码 ,当然由于时间的问题只是初步实现了


/**
 * 解析Cron 翻译成中文
 *
 * @author ZhuPengWei
 * @date 2018/5/18 15:26
 */
public class CronExpParserUtils {


    /**
     * Cron 表达式->中文描述
     *
     * @param corn core表达式
     * @return 中文描述
     */
    public static String cronConvertToChinese(String corn) {

        StringBuilder result = new StringBuilder();

        String[] cornArray = corn.split(" ");

        // 解析cornArray
        if (cornArray[1].equals(cornArray[2]) && cornArray[2].equals(cornArray[3]) && cornArray[3].equals(cornArray[4]) && cornArray[1].equals("*")) {
            result = everyMinutes(result);
        } else if (!cornArray[1].equals(cornArray[2]) && cornArray[2].equals(cornArray[3]) && cornArray[3].equals(cornArray[4]) && cornArray[2].equals("*")) {
            result = everyHour(result, cornArray);
        } else if (!cornArray[2].equals(cornArray[3]) && cornArray[3].equals(cornArray[4]) && cornArray[3].equals("*")) {
            result = everDay(result, cornArray);
        } else if (!cornArray[3].equals(cornArray[4]) && cornArray[4].equals("*") && cornArray[5].equals("?")) {
            result = everyMonthDay(result, cornArray);
        } else if (!cornArray[5].equals("?") && cornArray[3].equals("?")) {
            result = everyMonthWeek(result, cornArray);
        } else if (!cornArray[1].equals("*") && !cornArray[2].equals("*") && !cornArray[3].equals("*") && !cornArray[4].equals("*") && cornArray[5].equals("?")) {
            result = everyYear(result, cornArray);
        } else {
            result.append("暂时不能解析");
        }


        return result.toString();
    }


    /**
     * 每分钟 执行
     *
     * @return 结果
     */
    private static StringBuilder everyMinutes(StringBuilder stringBuilder) {
        return stringBuilder.append("每分钟发送消息");
    }

    /**
     * 每小时每分钟
     *
     * @param stringBuilder 字符串拼接对象
     * @param cornArray         core字符串数组
     * @return 结果
     */
    private static StringBuilder everyHour(StringBuilder stringBuilder, String[] cornArray) {
        if (cornArray[1].equals("0")) {
            return stringBuilder.append("每小时发送消息");
        }
        return stringBuilder.append("每小时的第").append(cornArray[1]).append("分钟发送消息");
    }

    /**
     * 每天每小时
     *
     * @param stringBuilder 字符串拼接对象
     * @param cornArray         core字符串数组
     * @return 结果
     */
    private static StringBuilder everDay(StringBuilder stringBuilder, String[] cornArray) {
        if (cornArray[1].equals("*")) {
            return stringBuilder.append("每天的第").append(cornArray[2]).append("小时么每过一分钟发送消息");
        }
        return stringBuilder.append("每天的").append(cornArray[2]).append("时").append(cornArray[1]).append("分发送消息");
    }


    /**
     * 每月第几天
     *
     * @param stringBuilder 字符串拼接对象
     * @param cornArray         core字符串数组
     * @return 结果
     */
    private static StringBuilder everyMonthDay(StringBuilder stringBuilder, String[] cornArray) {
        if (cornArray[1].equals("*") && cornArray[2].equals("*")) {
            return everyMinutes(stringBuilder);
        }
        if (cornArray[2].equals("*")) {
            return everyHour(stringBuilder, cornArray);
        }
        if (cornArray[1].equals("*")) {
            return everDay(stringBuilder, cornArray);
        }
        return stringBuilder.append("每月的第").append(cornArray[3]).append("天的").append(cornArray[2]).append("时").append(cornArray[1]).append("分发送消息");
    }


    /**
     * 星期
     *
     * @param stringBuilder 字符串拼接对象
     * @param cornArray         core字符串数组
     * @return 结果
     */
    private static StringBuilder everyMonthWeek(StringBuilder stringBuilder, String[] cornArray) {
        if (cornArray[1].equals("*") && cornArray[2].equals("*")) {
            return stringBuilder.append("每").append(cornArray[5]).append("每分钟发送消息");
        }
        if (cornArray[2].equals("*")) {
            return stringBuilder.append("每").append(cornArray[5]).append("的每小时的第").append(cornArray[1]).append("分发送消息");
        }
        if (cornArray[1].equals("*")) {
            return stringBuilder.append("每").append(cornArray[5]).append("的第").append(cornArray[2]).append("小时的每一分钟发送消息");
        }
        return stringBuilder.append("每").append(cornArray[5]).append("的第").append(cornArray[2]).append("时").append(cornArray[1]).append("分发送消息");
    }

    /**
     * 每年
     *
     * @param stringBuilder 字符串拼接对象
     * @param cornArray         core字符串数组
     * @return 结果
     */
    private static StringBuilder everyYear(StringBuilder stringBuilder, String[] cornArray) {
        return stringBuilder.append("每年").append(cornArray[4]).append("月").append(cornArray[3]).append("号").append(cornArray[2]).append("点").append(cornArray[1]).append("发送消息");
    }


}

因为每一个人的前端代码都不一样所以我就不粘贴前端代码了

Spring Boot 集成 Quartz 实现动态定时任务可以参考以下步骤: 1. 添加依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> ``` 2. 配置 Quartz 在 application.yml 文件中添加以下配置: ```yaml spring: quartz: job-store-type: MEMORY properties: org: quartz: jobStore: useProperties: true ``` 3. 编写任务类 编写需要执行的任务类,需要实现 org.quartz.Job 接口,例如: ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) { // 执行任务逻辑 } } ``` 4. 编写定时任务管理类 编写定时任务管理类,负责添加、修改和删除定时任务,例如: ```java @Service public class QuartzJobManager { @Autowired private Scheduler scheduler; public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class<? extends Job> jobClass, String cronExpression) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build(); CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName) .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).build(); scheduler.scheduleJob(jobDetail, trigger); } public void modifyJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String cronExpression) throws SchedulerException { TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).build(); scheduler.rescheduleJob(triggerKey, trigger); } public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) throws SchedulerException { JobKey jobKey = JobKey.jobKey(jobName, jobGroupName); TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); scheduler.pauseTrigger(triggerKey); scheduler.unscheduleJob(triggerKey); scheduler.deleteJob(jobKey); } } ``` 5. 测试 在需要执行定时任务的地方注入 QuartzJobManager,添加、修改和删除定时任务即可。 例如,添加一个每 5 秒执行一次的定时任务: ```java quartzJobManager.addJob("job1", "group1", "trigger1", "group1", MyJob.class, "0/5 * * * * ?"); ``` 注意,cronExpression 是一个 cron 表达式,可以根据需求自行修改。 以上就是 Spring Boot 集成 Quartz 实现动态定时任务的基本步骤,希望对你有帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值