您的位置:首页 > 编程语言 > Java开发

扩展: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类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  quartz2
相关文章推荐