quartz框架实现动态添加任务——细节问题

近期,项目需要,为了实现动态添加job任务,引入quartz框架,于是开始研究quartz框架,参考文章:http://snailxr.iteye.com/blog/2076903

文章中大部分内容涉及的是有cron表达式的触发器任务,如果需要立即执行的任务,

java代码如下:

public void runAJob(DataObject dataObject) throws SchedulerException {

    JobDetail jobDetail = JobBuilder.newJob(DataQuartzFactory.class)
    .withIdentity(dataObject.getJobId(), dataObject.getUserId()).storeDurably().build();

    jobDetail.getJobDataMap().put("key", dataObject);

    scheduler.addJob(jobDetail, true);

    JobKey jobKey = JobKey.jobKey(dataObject.getJobId(), dataObject.getUserId());

    scheduler.triggerJob(jobKey);

    scheduler.start();
}

jobdatamap中的key可以指定一个任意常量变量,dataObject即为任务类,保存了任务的所有信息,如jobid,userid等等信息,任务类可从数据库中取出,也可从队列中取出,取任务类方式自由制定。其中有一个细节问题是scheduler的注入,网上许多文章提到的xml配置为:

        class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />

实际上这样的配置在正常情况下是没有问题的,但是如果你的项目中还用到了spring配置的bean,并且该bean需要在quartz的业务实现类中用到(后面会谈到),那么必须对bean做一次转换,即将spring的bean注入到quartz框架中,那么正确的配置为:


       
           
       

   

其中JobBeanFactory代码如下:

public class JobBeanFactory extends SpringBeanJobFactory implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object jobInstance = super.createJobInstance(bundle);
        //把Job交给Spring来管理,这样Job就能使用由Spring产生的Bean了
        applicationContext.getAutowireCapableBeanFactory().autowireBean(jobInstance);
        return jobInstance;
    }
}

DataQuartzFactory需要实现Job接口的execute方法,这样quartz的schedule会调度执行该方法来实现异步任务的执行, java代码如下:


 public class DataQuartzFactory implements ApplicationContextAware, Job {

    @Autowired
    private XXService xxService;

    ApplicationContext  applicationContext;

    public void execute(JobExecutionContext context) throws JobExecutionException {

        DataObject dataObject = (DataObject) context.getMergedJobDataMap().get("key");
        
            xxService.doTask(dataObject);
        
        }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}
       

这里有一个非常值得注意的细节,大部分文章中都只提到需要实现Job接口,但是如果不实现ApplicationContextAware,那么xxService拿到是空指针,原理上面已经解释,不再赘述。

因此对于框架的使用,很多细节还是要掌握好,至于quartz大致原理什么的可以参考其他文章。



你可能感兴趣的:(技术类)