Quartz定时任务调度
一、简介
Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。Quartz 允许开发人员根据时间间隔(或天)来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。虽然可以通过属性文件(在属性文件中可以指定 JDBC 事务的数据源、全局作业和/或触发器侦听器、插件、线程池,以及更多)配置 Quartz,但它根本没有与应用程序服务器的上下文或引用集成在一起。结果就是作业不能访问 Web 服务器的内部函数;例如,在使用 WebSphere 应用服务器时,由 Quartz 调度的作业并不能影响服务器的动态缓存和数据源。
二、要使用Quartz,需要引入以下包
1、log4j-1.2.16
2、quartz-2.1.7
3、slf4j-api-1.6.1.jar
4、slf4j-log4j12-1.6.1.ja
三、了解几个接口
首先了解三个概念:
调度器 (Scheduler): 负责调度作业和触发器;
触发器(trigger) : 设置作业执行的时间、参数、条件等;(简单触发器和Cron触发器)
作业(Job) :定时任务内容,被执行的程序;
下载必要的jar包,直接去官网下载 (http://www.opensymphony.com/quartz/download.action),将quartz-x.x.x.jar 和core 和/或 optional 文件夹中的 jar 文件放在项目的文件夹或项目的类路径中
四、Quartz的几个核心的接口和类
Job接口: 自己写的“定时程序”实现此接口的void execute(JobExecutionContext arg0)方法,Job还有一类为有状态的StatefulJob接口,如果我们需要在上一个作业执行完后,根据其执行结果再进行下次作业的执行,则需要实现此接口。
Trigger抽象类: 调度类(Scheduler)在时间到时调用此类,再由trigger类调用指定的定时程序。
Quertz中提供了两类触发器为:SimpleTrigger,CronTrigger。前者用于实现比较简单的定时功能,例如几点开始,几点结束,隔多长时间执行,共执行多少次等,后者提供了使用表达式来描述定时功能,因此适用于比较复杂的定时描述,例如每个月的最后一个周五,每周的周四等。
JobDetail类: 具体某个定时程序的详细描述,包括Name,Group,JobDataMap等。
JobExecutionContext类: 定时程序执行的run-time的上下文环境,用于得到当前执行的Job的名字,配置的参数等。
JobDataMap类: 用于描述一个作业的参数,参数可以为任何基本类型例如String,float等,也可为某个对象的引用.
JobListener,TriggerListener接口: 用于监听触发器状态和作业扫行状态,在特写状态执行相应操作。
JobStore类: 在哪里执行定进程序,可选的有在内存中,在数据库中。
四、下面来配置Quartz框架在Spring中的引用
1.新建一个定时任务管理类,命名为QuartzJobManager
package com.shpte.paramfrm.quartz; import java.util.Map; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Controller; /** * @Description: 定时任务管理类 * * @ClassName: QuartzJobsManager */ @Controller public class QuartzJobsManager { @Autowired private SchedulerFactoryBean schedulerFactory; private String JOB_GROUP_NAME = "AFC_JOBGROUP_NAME"; private String TRIGGER_GROUP_NAME = "AFC_TRIGGERGROUP_NAME"; /** * @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名 * * @param jobName * 任务名 * @param cls * 任务 * @param time * 时间设置,参考quartz说明文档 * */ @SuppressWarnings("unchecked") public void addJob(String jobName, Class cls, String time) { try { Scheduler sched = schedulerFactory.getScheduler(); JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类 // 触发器 CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组 trigger.setCronExpression(time);// 触发器时间设定 sched.scheduleJob(jobDetail, trigger); // 启动 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public void addJob(String jobName, Class cls, String time, Map<String, Object> jobDataMap) { try { Scheduler sched = schedulerFactory.getScheduler(); JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类 jobDetail.getJobDataMap().putAll(jobDataMap); // 触发器 CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组 trigger.setCronExpression(time);// 触发器时间设定 sched.scheduleJob(jobDetail, trigger); // 启动 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 添加一个定时任务 * * @param jobName * 任务名 * @param jobGroupName * 任务组名 * @param triggerName * 触发器名 * @param triggerGroupName * 触发器组名 * @param jobClass * 任务 * @param time * 时间设置,参考quartz说明文档 */ @SuppressWarnings("unchecked") public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String time) { try { Scheduler sched = schedulerFactory.getScheduler(); JobDetail jobDetail = new JobDetail(jobName, jobGroupName, jobClass);// 任务名,任务组,任务执行类 // 触发器 CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);// 触发器名,触发器组 trigger.setCronExpression(time);// 触发器时间设定 sched.scheduleJob(jobDetail, trigger); } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名) * * @param jobName * @param time */ @SuppressWarnings("unchecked") public void modifyJobTime(String jobName, String time) { try { Scheduler sched = schedulerFactory.getScheduler(); CronTrigger trigger = (CronTrigger) sched.getTrigger(jobName, TRIGGER_GROUP_NAME); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { JobDetail jobDetail = sched.getJobDetail(jobName, JOB_GROUP_NAME); Class objJobClass = jobDetail.getJobClass(); removeJob(jobName); addJob(jobName, objJobClass, time); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 修改一个任务的触发时间 * * @param triggerName * @param triggerGroupName * @param time */ public void modifyJobTime(String triggerName, String triggerGroupName, String time) { try { Scheduler sched = schedulerFactory.getScheduler(); CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerName, triggerGroupName); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { CronTrigger ct = (CronTrigger) trigger; // 修改时间 ct.setCronExpression(time); // 重启触发器 sched.resumeTrigger(triggerName, triggerGroupName); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 移除一个任务(使用默认的任务组名,触发器名,触发器组名) * * @param jobName */ public void removeJob(String jobName) { try { Scheduler sched = schedulerFactory.getScheduler(); sched.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 停止触发器 sched.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除触发器 sched.deleteJob(jobName, JOB_GROUP_NAME);// 删除任务 } 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(); sched.pauseTrigger(triggerName, triggerGroupName);// 停止触发器 sched.unscheduleJob(triggerName, triggerGroupName);// 移除触发器 sched.deleteJob(jobName, jobGroupName);// 删除任务 } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description:启动所有定时任务 */ public void startJobs() { try { Scheduler sched = schedulerFactory.getScheduler(); sched.start(); } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description:关闭所有定时任务 * */ public void shutdownJobs() { try { Scheduler sched = schedulerFactory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { throw new RuntimeException(e); } } }
2、新建一个QuartzTestJob类来实现Job接口
package com.shpte.paramfrm.quartz.jobs; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class QuartzTestJob implements Job { @Override public void execute(JobExecutionContext jobCtx) throws JobExecutionException { // jobCtx.getJobDetail().getJobDataMap().get(key) System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "★★★★★★★★★★★"); //QuartzJobsManager.removeJob("动态任务调度"); } }
3、开始将Quartz与Spring整合
(1)、新建一个JobFactory继承AdaptableJobFactory类 package com.shpte.paramfrm.quartz.jobs; 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; 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; } }
(2)、新建一个applicationContext-quartz.xml文件,注入Quartz到Spring <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-lazy-init="true"> <description>定时任务</description> <bean id="schedulerFactoryBean" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" scope="singleton"> <property name="jobFactory"> <bean class="com.shpte.paramfrm.quartz.jobs.JobFactory"></bean> </property> </bean> </beans>
4、新建一个Job任务
package com.shpte.paramfrm.quartz.jobs; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.StatefulJob; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.shpte.common.param.manager.DraftParamManager; import com.shpte.dubbo.provider.IDraftParamService; public class QuartzEffectDraftParamLCC implements StatefulJob { private static final Logger log = LoggerFactory.getLogger(QuartzEffectDraftParamLCC.class); public static final String DEFAULT_JOB_NAME = "HBparam"; //这个 DEFAULT_JOB_NAME只给Quartz用 //0 0/30 * * * ? 每隔一分钟 执行一次 0 */1 * * * ? public static final String DEFAULT_JOB_TIME = " 0 5 9 22 2 ? 2017 "; //这个 DEFAULT_JOB_TIME只给Quartz用 public static final Integer REPLY_TIME_OUT = 300000; @Autowired public DraftParamManager draftParamManager; @Autowired public IDraftParamService draftParamService; @Override public void execute(JobExecutionContext jobCtx) throws JobExecutionException { log.info(" ★★★★★★★★★★★ 开始执行任务 : " + jobCtx.getJobDetail().getName()); if (!draftParamManager.effectiveDraftParam("DraftParamLcc",TinyTools.nowStr()))) { log.info("-----草稿参数生效失败------"); } else { log.info("-----草稿参数生效成功------"); } return; } }
5、添加一个Init()方法,调用任务类并且运行
这里调用了有三个任务,上面我只写了一个任务。
@PostConstruct private void init() { log.info(" ★★★★★★★★★★★ 启动默认任务 : " + QuartzEffectFutureParamCCHS.DEFAULT_JOB_NAME +" 触发时间:" + QuartzEffectFutureParamCCHS.DEFAULT_JOB_TIME); quartzJobsManager.addJob(QuartzEffectFutureParamCCHS.DEFAULT_JOB_NAME, QuartzEffectFutureParamCCHS.class, QuartzEffectFutureParamCCHS.DEFAULT_JOB_TIME); log.info(" ★★★★★★★★★★★ 启动默认任务 : " + QuartzEffectFutureParamLCC.DEFAULT_JOB_NAME +" 触发时间:" + QuartzEffectFutureParamLCC.DEFAULT_JOB_TIME); quartzJobsManager.addJob(QuartzEffectFutureParamLCC.DEFAULT_JOB_NAME, QuartzEffectFutureParamLCC.class, QuartzEffectFutureParamLCC.DEFAULT_JOB_TIME); log.info(" ★★★★★★★★★★★ 启动默认任务 : " + QuartzEffectDraftParamLCC.DEFAULT_JOB_NAME +" 触发时间:" + QuartzEffectDraftParamLCC.DEFAULT_JOB_TIME); quartzJobsManager.addJob(QuartzEffectDraftParamLCC.DEFAULT_JOB_NAME, QuartzEffectDraftParamLCC.class, QuartzEffectDraftParamLCC.DEFAULT_JOB_TIME
总结:以上就是一个完整的Quartz框架搭建、在Spring中整合、以及定制一个任务来在定时定点触发执行的完成步骤及完整代码。
);
loadParam();
}
6、看控制台日志
最怕你一生碌碌无为 还安慰自己平凡可贵