java 动态传corn,动态任务调度

最近有个需求,需要动态的去管理任务的调度,参考了网上的资料后就设计了如下方案。

1、设计一个任务表

CREATE TABLE `api_scheduler` (
  `job_name` varchar(128) NOT NULL COMMENT '任务名称',
  `trigger_name` varchar(128) NOT NULL COMMENT '触发器名称',
  `job_group_name` varchar(128) NOT NULL COMMENT '任务组',
  `trigger_group_name` varchar(128) NOT NULL COMMENT '触发器组',
  `is_vaild` varchar(1) NOT NULL DEFAULT '1' COMMENT '是否有效 1 有效  0无效',
  `class_path` varchar(128) NOT NULL COMMENT '类路径',
  `is_restart` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否重启该任务 1 重启  0不重启',
  `corn` varchar(256) NOT NULL COMMENT 'corn表达式',
  `restart_time` datetime DEFAULT NULL COMMENT '重启时间',
  `last_run_time` datetime DEFAULT NULL COMMENT '最后一次运行时间',
  PRIMARY KEY (`job_name`,`trigger_name`),
  UNIQUE KEY `job_name` (`job_name`),
  UNIQUE KEY `trigger_name` (`trigger_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在这里插入图片描述
然后再增加一个动态读取表里corn表达式的方法,然后根据corn动态的去改变调度。
2、注入scheduler

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

@Component("quartzJobFactory")
public class QuartzJobFactory  extends AdaptableJobFactory {
    //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfiguration {

    //注入scheduler到spring,在quartzManege会用到
    @Bean(name = "scheduler")
    public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {

        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setJobFactory(quartzJobFactory);
        factoryBean.afterPropertiesSet();
        Scheduler scheduler = factoryBean.getScheduler();
        scheduler.start();
        return scheduler;
    }
}

解决在job里注入bean使用为null的问题
3、实现方法 每秒读取一次

 @Scheduled(cron = "* * * * * ?")
    public void run() throws Exception {
//        log.info("The time is now {}", dateFormat.format(new Date()));

//        ===================================服务上的算法调用===================================
              List listScheduler = apiService.getSchedulerList();
        for(ApiScheduler api:listScheduler){
            try{

                String state = quartzManage.getJobState(api.getTriggerName(),api.getTriggerGroupName());
    //            log.info(" 任务 "+api.getJobName()+" 的状态为 "+state);
                // NONE(没有该job), NORMAL(正常), PAUSED(暂停), COMPLETE(完成), ERROR(错误), BLOCKED(阻塞)
                //如果任务有效
                if(StringUtils.equals(isVaild_yes,api.getIsVaild())){
                    //如果任务需要重启 修改了corn后需要重启
                    if(StringUtils.equals(api.getIsRestart(),isRestart_yes)){
                        log.info(" 任务 "+api.getJobName()+" 开始重启 ");
                        //需要重启
                        quartzManage.removeJob(api.getJobName(),api.getJobGroupName(),api.getTriggerName(),api.getTriggerGroupName());
                        doJob(api.getClassPath(),api.getJobName(),api.getJobGroupName(),api.getTriggerName(),api.getTriggerGroupName(),api.getCorn());
                        //更新状态
                        apiService.updateRestartTime(api.getJobName());
                    }else{
                        //不需要重启
                        //判断任务是否存在  如果不存在 则添加

                        if(StringUtils.equals(state,"NONE")){
                            log.info(" 任务 "+api.getJobName()+" 开始启动 ");
                            doJob(api.getClassPath(),api.getJobName(),api.getJobGroupName(),api.getTriggerName(),api.getTriggerGroupName(),api.getCorn());
                        }else if(StringUtils.equals(state,"PAUSED")||StringUtils.equals(state,"ERROR")){
                            log.info(" 任务 "+api.getJobName()+" 重新启动 ");
                            quartzManage.removeJob(api.getJobName(),api.getJobGroupName(),api.getTriggerName(),api.getTriggerGroupName());
                            doJob(api.getClassPath(),api.getJobName(),api.getJobGroupName(),api.getTriggerName(),api.getTriggerGroupName(),api.getCorn());
                        }
                    }

                }else {
                    if(!StringUtils.equals(state,"NONE")){
                        log.info(" 任务 "+api.getJobName()+" 移除 ");
                        quartzManage.removeJob(api.getJobName(),api.getJobGroupName(),api.getTriggerName(),api.getTriggerGroupName());
                    }
                }
            }catch (Exception e){
                log.error("任务"+api.getJobName()+"调度出现异常,异常信息为:"+e.getMessage());
            }
        }

//        log.info("-------------------------------------------------------------------------------------------------------------------");


//        ===================================服务上的算法调用===================================
    }

    /**
     * 添加任务调度
     * @param classPath
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupNam
     * @param corn
     * @throws ClassNotFoundException
     */
    public void doJob(String classPath,String jobName,String jobGroupName,String triggerName,String triggerGroupNam,String corn) throws ClassNotFoundException {
        Class jobClass = Class.forName(classPath);
        Map jobMap = new HashMap<>();
        QuartzManager.addJob(jobName,jobGroupName,triggerName,triggerGroupNam, jobClass,corn,jobMap);
    }

4、任务管理 (参考网上资料 然后加入了一些自己的方法)

 import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 任务调度管理
 *  gaoxueyong 2018.4.13
 */
@Component
public class QuartzManager {

    @Autowired
    private Scheduler scheduler;
    /**
     * @Description: 添加一个定时任务
     *
     * @param jobName 任务名
     * @param jobGroupName  任务组名
     * @param triggerName 触发器名
     * @param triggerGroupName 触发器组名
     * @param jobClass  任务
     * @param cron   时间设置,参考quartz说明文档
     * @param jobMap 参数
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public  void addJob(String jobName, String jobGroupName,
                              String triggerName, String triggerGroupName, Class jobClass,
                              String cron, Map jobMap) {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            // 任务名,任务组,任务执行类
            JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            //放置参数
            if(jobMap!=null){
                for(String key:jobMap.keySet()){
                    jobDetail.getJobDataMap().put(key,jobMap.get(key));
                }
            }
            jobDetail.getJobDataMap().put("jobName",jobName);
            // 触发器
            TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();

            // 调度容器设置JobDetail和Trigger
            scheduler.scheduleJob(jobDetail, trigger);

            // 启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description: 修改一个任务的触发时间
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName 触发器名
     * @param triggerGroupName 触发器组名
     * @param cron   时间设置,参考quartz说明文档
     */
    public  void modifyJobTime(String jobName,
                                     String jobGroupName, String triggerName, String triggerGroupName,
                                     String cron) {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }

            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                /** 方式一 :调用 rescheduleJob 开始 */
                // 触发器
                TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();

                // 触发器名,触发器组
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                // 触发器时间设定
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                // 创建Trigger对象
                trigger = (CronTrigger) triggerBuilder.build();
                // 方式一 :修改一个任务的触发时间
                scheduler.rescheduleJob(triggerKey, trigger);
                /** 方式一 :调用 rescheduleJob 结束 */

                /** 方式二:先删除,然后在创建一个新的Job  */
                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先删除,然后在创建一个新的Job */
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description: 移除一个任务
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     */
    public void removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName) {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();

            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            if(triggerKey!=null){
                scheduler.pauseTrigger(triggerKey);// 停止触发器
                scheduler.unscheduleJob(triggerKey);// 移除触发器
                scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description:启动所有定时任务
     */
    public  void startJobs() {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            scheduler.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description:关闭所有定时任务
     */
    public void shutdownJobs() {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            if (!scheduler.isShutdown()) {
                scheduler.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判断当前job是否存在
     * @param triggerName
     * @param triggerGroupName
     * @return NONE(没有该job), NORMAL(正常), PAUSED(暂停), COMPLETE(完成), ERROR(错误), BLOCKED(阻塞);
     */
    public String getJobState(String triggerName, String triggerGroupName){
        String flag = null;
        try {
//            Scheduler scheduler = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
            flag = state.toString();


        }catch (Exception e){
            flag = "ERROR";
        }finally {
            return flag;
        }
    }

}

5、具体执行的任务JOB

/**
 * 具体任务
 */
public class OtherAsapJob implements Job{
    private final Logger log = LoggerFactory.getLogger(OtherAsapJob.class);
    @Autowired
    private  ApiService apiService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        String jobName = jobDataMap.get("jobName").toString();
        log.info("job " +jobName+" is start");
        List listCategory = apiService.getApiCategoryList(jobName);
        List listInvoking = apiService.getApiInvokingParamList(jobName);
        try {
            DoExcuteJob.start(listCategory,listInvoking);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //更新最后一次运行的时间
        apiService.updateLastRunTime(jobName);
        log.info("job " +jobName+" is end");
    }
}


所使用的jar包

  
    
      org.quartz-scheduler
      quartz
      2.3.0
    
    
    
      org.springframework
      spring-context-support
    

你可能感兴趣的:(编程开发)