扩展:spring3整合quartz2,实现动态添加、删除定时任务
2018-03-08 15:38
651 查看
一、Quartz简介 Quartz大致可分为三个主要的核心: 1、调度器Scheduler:是一个计划调度器容器,容器里面可以盛放众多的JobDetail和Trigger,当容器启动后,里面的每个JobDetail都会根据Trigger按部就班自动去执行. 2、任务Job:要执行的具体内容。JobDetail:具体的可执行的调度程序,包含了这个任务调度的方案和策略。 3、触发器Trigger:调度参数的配置,什么时候去执行调度。原理:可以这么理解它的原理:调度器就相当于一个容器,装载着任务和触发器。任务和触发器又是绑定在一起的,然而一个任务可以对应多个触发器,但一个触发器却只能对应一个任务。当JobDetail和Trigger在scheduler容器上注册后,形成了装配好的任务作业(JobDetail和Trigger所组成的一对儿),就可以伴随容器启动而调度执行了。二、与spring的整合 本文的用的是quartz-2.2.1与spring-3.2.2。之所以在这里特别对版本作一下说明,是因为spring和quartz的整合对版本是有要求的。spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。原因主要是:spring对于quartz的支持实现,org.springframework.scheduling.quartz.CronTriggerBean继承了 org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是个类,而在 quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器 (trigger)。spring中使用quartz有两种方式,具体请看http://blog.csdn.net/liuxiao723846/article/details/46879077三、动态整合 上面的整合只能应付简单的需求,但很多时候我们遇到的是需要动态的添加、暂停、修改任务。而spring中所提供的定时任务组件却只能够通过修改xml中trigger的配置才能控制定时任务的时间以及任务的启用或停止,这在带给我们方便的同时也失去了动态配置任务的灵活性。 所以我们就得换种方式来解决。把任务与cronExpression存放在数据库中,最大化减少xml配置,创建一个工厂类,在实际调用时把任务的相关信息通过参数方式传入,由该工厂类根据任务信息来具体执行需要的操作,从而方便我们的动态修改。
Maven <!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
1.spring配置(其实只要这一行足矣,去掉了原先"taskJob"、"myTrigger"等配置):<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />2.任务执行入口(就是在这里执行quartz容器中的任务的),实现Job接口,类似工厂类:package com.es.quartz;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.quartz.DisallowConcurrentExecution;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.beans.factory.annotation.Autowired;import com.es.entry.ExportTask;import com.es.service.TaskExportService;import<
2031d
/strong> com.es.utils.exception.BusinessException;/** * 定时任务运行工厂类 * [b]@author Administrator *Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。 1.在Spring中这时需要设置concurrent的值为false, 禁止并发执行。 <property name="concurrent" value="true" /> 2.当不使用spring的时候就需要在Job的实现类上加@DisallowConcurrentExecution的注释 设置@DisallowConcurrentExecution以后程序会等任务执行完毕以后再去执行,否则会在3秒时再启用新的线程执行 */@DisallowConcurrentExecutionpublic class QuartzJob implements Job { private Logger myLogger = LogManager.getLogger("QuartzJobFactory"); @Autowired private TaskExportService taskExportService; @Override public void execute(JobExecutionContext context) throws JobExecutionException { try { ExportTask task = (ExportTask) context.getJobDetail().getJobDataMap().get("task");// context.getJobDetail().getJobDataMap().v myLogger.info(task.getName()+":任务成功运行"); if("exact".equals(task.getSearchType())){ taskExportService.runTaskAutomaticForExact(task); } } catch (BusinessException e) { e.printStackTrace(); } myLogger.info("任务成功运行完成"); }}
3、创建任务类。既然要动态修改任务,那任务就得保存在某个地方。一个po类package com.es.entry;public class ExportTask { private Integer id; private String name;//任务名 private String export_cron;//cron表达式 private String start_time;//开始时间 private String run_time;//运行时长 private Integer status;//'状态(0:未运行,1:运行中,2:运行完成) private String file_url;//文件地址 private String params;//查询参数 private Integer type;//调用类型(0:手动,1:周期) private String searchType;//检索类型 private Integer createUserId;//创建人id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getExport_cron() { return export_cron; } public void setExport_cron(String export_cron) { this.export_cron = export_cron; } public String getStart_time() { return start_time; } public void setStart_time(String start_time) { this.start_time = start_time; } public String getRun_time() { return run_time; } public void setRun_time(String run_time) { this.run_time = run_time; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getFile_url() { return file_url; } public void setFile_url(String file_url) { this.file_url = file_url; } public String getParams() { return params; } public void setParams(String params) { this.params = params; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public String getSearchType() { return searchType; } public void setSearchType(String searchType) { this.searchType = searchType; } public Integer getCreateUserId() { return createUserId; } public void setCreateUserId(Integer createUserId) { this.createUserId = createUserId; }}4.在这里进行任务的增删改查接口:package com.es.quartz;
import java.util.List;import com.es.entry.ExportTask;import com.es.utils.exception.BusinessException;public interface QuartzManager { /** * 向容器中添加任务 * @param task * @throws BusinessException */ public void addJob(ExportTask task) throws BusinessException; /** * 从容器中删除任务 * @param jobnames * @throws BusinessException */ public void removeJob(List<String> jobnames) throws BusinessException; }实现类:package com.es.quartz.impl;import java.util.List;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.TriggerBuilder;import org.quartz.TriggerKey;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.quartz.SchedulerFactoryBean;import org.springframework.stereotype.Component;import com.es.entry.ExportTask;import com.es.quartz.QuartzJob;import com.es.quartz.QuartzManager;import com.es.utils.exception.BusinessException;@Componentpublic class QuartzManagerImpl implements QuartzManager { private Logger log = LogManager.getLogger("QuartzManagerImpl"); @Autowired private SchedulerFactoryBean schedulerFactoryBean; @Override public void addJob(ExportTask task) throws BusinessException { log.info("addJob start:"+(task.getName()+"@"+task.getId())); Scheduler scheduler =schedulerFactoryBean.getScheduler(); //任务构建withIdentity:相当于给任务起了个名字 JobDetail jobDetail =JobBuilder.newJob(QuartzJob.class).withIdentity(new JobKey(task.getName()+"@"+task.getId())).build(); jobDetail.getJobDataMap().put("task", task); //表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getExport_cron()); //按新的cronExpression表达式构建一个新的trigger:withIdentity:相当于给trigger起了个名字 CronTrigger trigger = TriggerBuilder.newTrigger().withSchedule(scheduleBuilder).withIdentity(new TriggerKey(task.getName()+"@"+task.getId())).build(); try { scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { throw new BusinessException(e, (task.getName()+"@"+task.getId())+":quartz添加job异常"); } } @Override public void removeJob(List<String> jobnames) throws BusinessException { log.info("removeJob start :"+jobnames.size()); if(null==jobnames||jobnames.isEmpty()){ throw new BusinessException(jobnames+":quartz删除job 参数异常"); } Scheduler scheduler =schedulerFactoryBean.getScheduler(); try { for(String name:jobnames){ scheduler.pauseTrigger(new TriggerKey(name));// 停止触发器 scheduler.unscheduleJob(new TriggerKey(name));//移除触发器 scheduler.deleteJob(new JobKey(name));//删除任务 } } catch (SchedulerException e) { throw new BusinessException(e, jobnames+":quartz删除job异常"); } }}5.quartz的Job中注入spring对象一般情况下,quartz的job中使用autowired注解注入的对象为空,这时候我们就要使用spring-quartz提供的AdaptableJobFactory类自定义一个类:package com.es.quartz;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;/*** 一般情况下,quartz的job中使用autowired注解注入的对象为空,* 这时候我们就要使用spring-quartz提供的AdaptableJobFactory类。* @author Administrator**/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; }}
然后将spring中配置改为如下:<!-- quartz --> <bean id="jobFactory" class="com.es.quartz.JobFactory"></bean> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" > <property name="jobFactory" ref="jobFactory"></property> </bean>这时候我们就可以在Job的实现类中使用autowired注入service对象了,如QuartzJob类。
Maven <!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
1.spring配置(其实只要这一行足矣,去掉了原先"taskJob"、"myTrigger"等配置):<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />2.任务执行入口(就是在这里执行quartz容器中的任务的),实现Job接口,类似工厂类:package com.es.quartz;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.quartz.DisallowConcurrentExecution;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.beans.factory.annotation.Autowired;import com.es.entry.ExportTask;import com.es.service.TaskExportService;import<
2031d
/strong> com.es.utils.exception.BusinessException;/** * 定时任务运行工厂类 * [b]@author Administrator *Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。 1.在Spring中这时需要设置concurrent的值为false, 禁止并发执行。 <property name="concurrent" value="true" /> 2.当不使用spring的时候就需要在Job的实现类上加@DisallowConcurrentExecution的注释 设置@DisallowConcurrentExecution以后程序会等任务执行完毕以后再去执行,否则会在3秒时再启用新的线程执行 */@DisallowConcurrentExecutionpublic class QuartzJob implements Job { private Logger myLogger = LogManager.getLogger("QuartzJobFactory"); @Autowired private TaskExportService taskExportService; @Override public void execute(JobExecutionContext context) throws JobExecutionException { try { ExportTask task = (ExportTask) context.getJobDetail().getJobDataMap().get("task");// context.getJobDetail().getJobDataMap().v myLogger.info(task.getName()+":任务成功运行"); if("exact".equals(task.getSearchType())){ taskExportService.runTaskAutomaticForExact(task); } } catch (BusinessException e) { e.printStackTrace(); } myLogger.info("任务成功运行完成"); }}
3、创建任务类。既然要动态修改任务,那任务就得保存在某个地方。一个po类package com.es.entry;public class ExportTask { private Integer id; private String name;//任务名 private String export_cron;//cron表达式 private String start_time;//开始时间 private String run_time;//运行时长 private Integer status;//'状态(0:未运行,1:运行中,2:运行完成) private String file_url;//文件地址 private String params;//查询参数 private Integer type;//调用类型(0:手动,1:周期) private String searchType;//检索类型 private Integer createUserId;//创建人id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getExport_cron() { return export_cron; } public void setExport_cron(String export_cron) { this.export_cron = export_cron; } public String getStart_time() { return start_time; } public void setStart_time(String start_time) { this.start_time = start_time; } public String getRun_time() { return run_time; } public void setRun_time(String run_time) { this.run_time = run_time; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getFile_url() { return file_url; } public void setFile_url(String file_url) { this.file_url = file_url; } public String getParams() { return params; } public void setParams(String params) { this.params = params; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public String getSearchType() { return searchType; } public void setSearchType(String searchType) { this.searchType = searchType; } public Integer getCreateUserId() { return createUserId; } public void setCreateUserId(Integer createUserId) { this.createUserId = createUserId; }}4.在这里进行任务的增删改查接口:package com.es.quartz;
import java.util.List;import com.es.entry.ExportTask;import com.es.utils.exception.BusinessException;public interface QuartzManager { /** * 向容器中添加任务 * @param task * @throws BusinessException */ public void addJob(ExportTask task) throws BusinessException; /** * 从容器中删除任务 * @param jobnames * @throws BusinessException */ public void removeJob(List<String> jobnames) throws BusinessException; }实现类:package com.es.quartz.impl;import java.util.List;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.TriggerBuilder;import org.quartz.TriggerKey;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.quartz.SchedulerFactoryBean;import org.springframework.stereotype.Component;import com.es.entry.ExportTask;import com.es.quartz.QuartzJob;import com.es.quartz.QuartzManager;import com.es.utils.exception.BusinessException;@Componentpublic class QuartzManagerImpl implements QuartzManager { private Logger log = LogManager.getLogger("QuartzManagerImpl"); @Autowired private SchedulerFactoryBean schedulerFactoryBean; @Override public void addJob(ExportTask task) throws BusinessException { log.info("addJob start:"+(task.getName()+"@"+task.getId())); Scheduler scheduler =schedulerFactoryBean.getScheduler(); //任务构建withIdentity:相当于给任务起了个名字 JobDetail jobDetail =JobBuilder.newJob(QuartzJob.class).withIdentity(new JobKey(task.getName()+"@"+task.getId())).build(); jobDetail.getJobDataMap().put("task", task); //表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getExport_cron()); //按新的cronExpression表达式构建一个新的trigger:withIdentity:相当于给trigger起了个名字 CronTrigger trigger = TriggerBuilder.newTrigger().withSchedule(scheduleBuilder).withIdentity(new TriggerKey(task.getName()+"@"+task.getId())).build(); try { scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { throw new BusinessException(e, (task.getName()+"@"+task.getId())+":quartz添加job异常"); } } @Override public void removeJob(List<String> jobnames) throws BusinessException { log.info("removeJob start :"+jobnames.size()); if(null==jobnames||jobnames.isEmpty()){ throw new BusinessException(jobnames+":quartz删除job 参数异常"); } Scheduler scheduler =schedulerFactoryBean.getScheduler(); try { for(String name:jobnames){ scheduler.pauseTrigger(new TriggerKey(name));// 停止触发器 scheduler.unscheduleJob(new TriggerKey(name));//移除触发器 scheduler.deleteJob(new JobKey(name));//删除任务 } } catch (SchedulerException e) { throw new BusinessException(e, jobnames+":quartz删除job异常"); } }}5.quartz的Job中注入spring对象一般情况下,quartz的job中使用autowired注解注入的对象为空,这时候我们就要使用spring-quartz提供的AdaptableJobFactory类自定义一个类:package com.es.quartz;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;/*** 一般情况下,quartz的job中使用autowired注解注入的对象为空,* 这时候我们就要使用spring-quartz提供的AdaptableJobFactory类。* @author Administrator**/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; }}
然后将spring中配置改为如下:<!-- quartz --> <bean id="jobFactory" class="com.es.quartz.JobFactory"></bean> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" > <property name="jobFactory" ref="jobFactory"></property> </bean>这时候我们就可以在Job的实现类中使用autowired注入service对象了,如QuartzJob类。
相关文章推荐
- Spring3整合Quartz2实现定时任务及动态任务调整(添加删除暂停恢复)--推荐
- Spring 3整合Quartz 2实现定时任务二:动态添加任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务二:动态添加任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务二:动态添加任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务:动态添加任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务二:动态添加任务
- Spring 3整合Quartz 2实现定时任务二:动态添加任务
- Spring 3整合Quartz 2实现定时任务二:动态添加任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- Spring 3整合Quartz 2实现定时任务二:动态添加任务