Quartz Job & Spring 动态任务调度

来源:互联网 发布:sharepoint是什么软件 编辑:程序博客网 时间:2024/03/29 22:55

Quartz Job & Spring

在实际项目应用中经常会用到定时任务,可通过Quartz框架轻松完成。在Web项目中,如果用Spring框架管理Quartz,在Web容器启动或关闭时自动启动、关闭Quartz中的任务,非常方便。

传统的MethodInvokingJobDetailFactoryBean运行方式,配置复杂,且不够灵活——如果要动态改变任务的状态、cron表达式等就需要改变配置甚至代码需要重启服务器了。因此,我采取动态任务调度的方式,可自由控制任务进度,更可以显示到html页面上。

这里写图片描述

配置

只需要在Spring配置文件中加上SchedulerFactoryBean。

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no"></bean>

这样,Spring就为我们创建了一个空的Scheduler,我们后面手动添加任务进去。

任务

我们定义一个Job类,任务都在这个Job类上执行

public class QuartzJobFactory implements Job {    public void execute(JobExecutionContext context)             throws JobExecutionException{        System.out.println("任务执行了");    }}

既然记录任务状态,那就需要定义一个类了,我们定义一个ScheduleJob

public class ScheduleJobDomain {    private String jobId;    //任务id    private String jobName;  //任务名称    /** 任务状态 */    private String jobStatus;    private String quartz;   //cron表达式    //省略get、set方法}

再定义一个Service

/** * 管理quartz任务的service */public interface ScheduleJobService {    //获取所有计划中的任务    List<ScheduleJobDomain> getPlanJobs() throws SchedulerException;    //获取所有运行中的任务    List<ScheduleJobDomain> getRunningJobs() throws SchedulerException;    //暂停任务    void pauseJob(ScheduleJobDomain scheduleJob) throws SchedulerException;    //恢复任务    void resumeJob(ScheduleJobDomain scheduleJob) throws SchedulerException;    //删除任务    void deleteJob(ScheduleJobDomain scheduleJob) throws SchedulerException;    //立即运行任务 ,只会运行一次    void runOnce(ScheduleJobDomain scheduleJob) throws SchedulerException;    //更新任务的时间表达式    void updateExpression(ScheduleJobDomain job,String expression) throws SchedulerException;    //添加任务    void addJob(ScheduleJobDomain scheduleJob) throws SchedulerException;}

Service的实现类如下

@Servicepublic class ScheduleJobServiceImpl implements ScheduleJobService {    @Autowired    private Scheduler scheduler;    @Override    public List<ScheduleJobDomain> getPlanJobs() throws SchedulerException {        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);        List<ScheduleJobDomain> jobList = new ArrayList<ScheduleJobDomain>();        for(JobKey jobKey  : jobKeys){            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);            for (Trigger trigger : triggers){                ScheduleJobDomain job = (ScheduleJobDomain) trigger.getJobDataMap().get("scheduleJob");                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());                job.setJobStatus(triggerState.name());                if (trigger instanceof CronTrigger) {                    CronTrigger cronTrigger = (CronTrigger) trigger;                    String cronExpression = cronTrigger.getCronExpression();                    job.setQuartz(cronExpression);                }                jobList.add(job);            }        }        return jobList;    }    @Override    public List<ScheduleJobDomain> getRunningJobs() throws SchedulerException {        List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();        List<ScheduleJobDomain> jobList = new ArrayList<ScheduleJobDomain>();        for (JobExecutionContext executingJob : executingJobs){            Trigger trigger = executingJob.getTrigger();            ScheduleJobDomain job = (ScheduleJobDomain) trigger.getJobDataMap().get("scheduleJob");            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());            job.setJobStatus(triggerState.name());            if (trigger instanceof CronTrigger) {                CronTrigger cronTrigger = (CronTrigger) trigger;                String cronExpression = cronTrigger.getCronExpression();                job.setQuartz(cronExpression);            }            jobList.add(job);        }        return jobList;    }    @Override    public void pauseJob(ScheduleJobDomain scheduleJob) throws SchedulerException {        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());        scheduler.pauseJob(jobKey);    }    @Override    public void resumeJob(ScheduleJobDomain scheduleJob) throws SchedulerException {        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());        scheduler.resumeJob(jobKey);    }    @Override    public void deleteJob(ScheduleJobDomain scheduleJob) throws SchedulerException {        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());        scheduler.deleteJob(jobKey);    }    @Override    public void runOnce(ScheduleJobDomain scheduleJob) throws SchedulerException {        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());        scheduler.triggerJob(jobKey);    }    @Override    public void updateExpression(ScheduleJobDomain scheduleJob, String expression) throws SchedulerException {        TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(),                scheduleJob.getJobGroup());        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(expression);        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)                .withSchedule(scheduleBuilder).build();        scheduler.rescheduleJob(triggerKey, trigger);    }    @Override    public void addJob(ScheduleJobDomain scheduleJob) throws SchedulerException {        TriggerKey key = TriggerKey.triggerKey(scheduleJob.getJobName(),scheduleJob.getJobGroup());        Trigger trigger = scheduler.getTrigger(key);        if(trigger == null){            //在创建任务时如果不存在新建一个            JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)                    .withIdentity(scheduleJob.getJobName(),scheduleJob.getJobGroup()).build();            jobDetail.getJobDataMap().put("scheduleJob",scheduleJob);            //表达式调度构建器            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getQuartz());            //按新的cronExpression表达式构建一个新的trigger            trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(),scheduleJob.getJobGroup())                    .withSchedule(scheduleBuilder).build();            trigger.getJobDataMap().put("scheduleJob",scheduleJob);            scheduler.scheduleJob(jobDetail,trigger);        }else{            // Trigger已存在,那么更新相应的定时设置            //表达式调度构建器            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getQuartz());            trigger = TriggerBuilder.newTrigger().withIdentity(key).withSchedule(scheduleBuilder).build();            trigger.getJobDataMap().put("scheduleJob",scheduleJob);            //重新执行            scheduler.rescheduleJob(key,trigger);        }    }

这样,我们在页面Controller中,就可以直接使用BankJobService来管理任务的状态了。

在Job中如何得到Spring的Bean

由于Job对象是Quartz创建的,它没有被注册到Spring容器中,因此无法直接通过@Autowired得到Spring的Bean对象,解决方式是从BankJobServiceImpl中拿到需要的SpringBean,然后在addJob时放到JobDetail里面去。

比如拿到Mybatis的SqlSessionTemplate。

public class BankJobServiceImpl{    @Autowired    private SqlSessionTemplate sqlSessionTemplate;}

在addJob方法里面, 修改

JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)                                 .withIdentity(scheduleJob.getJobName(),scheduleJob.getJobGroup()).build();jobDetail.getJobDataMap().put("sqlSessionTemplate",sqlSessionTemplate);

然后在QuartzJobFactory中

public void execute(JobExecutionContext context) throws JobExecutionException{    SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) context.getMergedJobDataMap().get("sqlSessionTemplate");}
原创粉丝点击