Quartz是OpenSymphony开源组织在Job scheduling领域的一个开源项目,是一款清新友好的任务调度框架。
Quartz两大基本功能是job和SimpleTrigger(作业和触发器)。
基本组成
核心的是Scheduler类。
有以下几个相关类:
Scheduler:定时任务调度;
Job:任务类需要实现的接口;
JobDetail:Job的实例,被Scheduler执行的是JobDetail,而不是Job;
Trigger:触发Job的执行;
JobBuilder:定义和创建JobDetail实例的接口;
TriggerBuilder:定义和创建Trigger实例的接口;
作业和触发器,是一对多的关系,每一个Job,都仅对应一个JobDetail。
不使用配置文件
作业
继承Job接口并实现execute方法,或是继承QuartzJobBean并实现executeInternal方法:
public class SimpleQuartzJob implements Job { public SimpleQuartzJob() { } public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("In SimpleQuartzJob - executing its JOB at " + new Date() + " by " + context.getTrigger().getName()); } }
execute 方法接受一个 JobExecutionContext 对象作为参数,提供了job实例的上下文
触发器
通过触发器启动任务:
public void task() throws SchedulerException { // Initiate a Schedule Factory SchedulerFactory schedulerFactory = new StdSchedulerFactory(); // Retrieve a scheduler from schedule factory Scheduler scheduler = schedulerFactory.getScheduler(); long ctime = System.currentTimeMillis(); // Initiate JobDetail with job name, job group, and executable job class JobDetail jobDetail = new JobDetail("jobDetail-s1", "jobDetailGroup-s1", SimpleQuartzJob.class); // Initiate SimpleTrigger with its name and group name SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger", "triggerGroup-s1"); // set its start up time simpleTrigger.setStartTime(new Date(ctime)); // set the interval, how often the job should run (10 seconds here) simpleTrigger.setRepeatInterval(10000); // set the number of execution of this job, set to 10 times. simpleTrigger.setRepeatCount(100); /** set the ending time of this job. * We set it for 60 seconds from its startup time here * Even if we set its repeat count to 10, * this will stop its process after 6 repeats as it gets it endtime by then.*/ simpleTrigger.setEndTime(new Date(ctime + 60000L)); // set priority of trigger. If not set, the default is 5 simpleTrigger.setPriority(10); // schedule a job with JobDetail and Trigger scheduler.scheduleJob(jobDetail, simpleTrigger); // start the scheduler scheduler.start(); }
Cron触发器
可使用触发器快捷的调用定时任务(Spring有自身的定时任务cron触发器,类似),Corn包含以下七个字段:
秒 分 时 月内日期 月 周内日期 年(可选)
特殊符号:
/:增量,分位5/15表示5分开始 每15分钟增量
?:忽略,忽略该位,限定月内日、周内日可用
*:通配,所有有效
数字后W:指定工作日,如月1W为第一个工作日
(0/5 * * * * ?)代表每五秒钟执行一次
public void task() throws SchedulerException { // Initiate a Schedule Factory SchedulerFactory schedulerFactory = new StdSchedulerFactory(); // Retrieve a scheduler from schedule factory Scheduler scheduler = schedulerFactory.getScheduler(); long ctime = System.currentTimeMillis(); // Initiate JobDetail with job name, job group, and executable job class JobDetail jobDetail = new JobDetail("jobDetail2", "jobDetailGroup2", SimpleQuartzJob.class); // Initiate CronTrigger with its name and group name CronTrigger cronTrigger = new CronTrigger("cronTrigger", "triggerGroup2"); try { // setup CronExpression CronExpression cexp = new CronExpression("0/5 * * * * ?"); // Assign the CronExpression to CronTrigger cronTrigger.setCronExpression(cexp); } catch (Exception e) { e.printStackTrace(); } // schedule a job with JobDetail and Trigger scheduler.scheduleJob(jobDetail, cronTrigger); // start the scheduler scheduler.start(); }
使用xml配置任务
<bean id="timedtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <bean class="com.timetask.TimeTask" /> <!-- 任务 --> </property> <property name="targetMethod" value="run" /> <!-- 作业执行方法(注意:这里不再继承Job类) --> <property name="concurrent" value="false" /><!-- 作业不并发调度 --> </bean> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="timedtask" /> <property name="cronExpression" value="0 0 3 * * ?" /> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="timedtask" /> <property name="startDelay" value="0" /><!-- 延迟0秒 --> <property name="repeatInterval" value="5000" /><!-- 每5秒调度一次 --> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger" /> <ref bean="cronTrigger" /> </list> </property> </bean>
在Springboot中使用Quartz(注解)
引入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
写Job:
public class TestQuartz extends QuartzJobBean { /** * 执行任务 * @param jobExecutionContext * @throws JobExecutionException */ @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("Test task"+new Date()); } }
配置调度、触发器,这里提供了三种示范:
@Configuration public class QuartzConfig { @Bean(name = "myJob") public JobDetail testQuartzDetail(){ return JobBuilder.newJob(TestQuartz.class) .withIdentity("testQuartz","testQuartz_group") // 执行中应用发生故障,会重新执行 .requestRecovery() // 即使没有Trigger关联,也不删除该JobDetail,而是将其加入队列,等待一个sched.scheduleJob .storeDurably() .build(); } @Bean(name = "scheduleBuilder") public SimpleScheduleBuilder scheduleBuilder(){ SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(10) //设置时间周期单位秒 //.repeatSecondlyForTotalCount(5);//指定执行次数 .repeatForever(); //始终执行 return scheduleBuilder; } //2.0+ trigger @Bean(name = "simpleTrigger") public Trigger testQuartzSimpleTrigger( @Qualifier("scheduleBuilder")ScheduleBuilder scheduleBuilder, @Qualifier("myJob")JobDetail job){ return TriggerBuilder.newTrigger().forJob(job) .withIdentity("testQuartzTrigger","triggerGroup") .withSchedule(scheduleBuilder) .build(); } //Spring2.0之前 CornTrigger @Bean(name = "cornTrigger") public CronTriggerFactoryBean CornTrigger(@Qualifier("myJob")JobDetail job) { CronTriggerFactoryBean trigger = new CronTriggerFactoryBean(); trigger.setJobDetail(job); trigger.setCronExpression("0/10 * * * * ?"); trigger.setName("cornTrigger"); return trigger; } //2.0+ cornTrigger @Bean(name = "cornTrigger2") public Trigger SecondCornTrigger(@Qualifier("myJob")JobDetail job) { Trigger trigger=TriggerBuilder.newTrigger().forJob(job) .withIdentity("cornTrigger2", "triggerGroup") .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *")) .startNow() //其实默认即是startNow() .build(); return trigger; } }
这样配置好的任务会直接被调度触发,一个JobDetail同时注入了三个Trigger,运行结果是每十秒输出三组数据。
配置properties:
# 线程调度器实例名 org.quartz.scheduler.instanceName = quartzScheduler # 线程池的线程数,即最多3个任务同时跑 org.quartz.threadPool.threadCount = 3 # 使用内存存储任务和触发器等信息 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
配置:
@Configuration public class QuartzConfigration { @Autowired private JobFactory jobFactory; @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setJobFactory(jobFactory); // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job schedulerFactoryBean.setOverwriteExistingJobs(true); schedulerFactoryBean.setStartupDelay(1); return schedulerFactoryBean; } @Bean public Scheduler scheduler() { return schedulerFactoryBean().getScheduler(); } }
配置jobFactory:
@Component 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; } }
注册组件(这里省略了任务类):
@Configuration public class QuartzJobConfig { /** * MethodInvokingJobDetailFactoryBean */ @Bean(name = "myJobBean") public MethodInvokingJobDetailFactoryBean myJobBean( MyJob myJob) { MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean(); jobDetail.setConcurrent(false); jobDetail.setName("general-myJob"); jobDetail.setGroup("general"); jobDetail.setTargetObject(myJob); jobDetail.setTargetMethod("myJobBusinessMethod"); return jobDetail; } /** * CornTriggerFacyoryBean */ @Bean(name = "myJobTrigger") public CronTriggerFactoryBean myJobTrigger(@Qualifier("myJobBean") MethodInvokingJobDetailFactoryBean myJobDetailFactoryBean) { CronTriggerFactoryBean trigger = new CronTriggerFactoryBean(); trigger.setJobDetail(myJobDetailFactoryBean.getObject()); trigger.setCronExpression("0/10 * * * * ?"); trigger.setName("general-myJobTrigger"); return trigger; } }
把job和触发器注册到调度器:
@Configuration public class QuartzConfig { /** * 调度器工厂Bean */ @Bean(name = "schedulerFactory") public SchedulerFactoryBean schedulerFactory( @Qualifier("myFirstExerciseJobTrigger") Trigger myFirstExerciseJobTrigger, @Qualifier("mySecondExerciseJobTrigger") Trigger mySecondExerciseJobTrigger) { SchedulerFactoryBean bean = new SchedulerFactoryBean(); // 覆盖已存在的任务 bean.setOverwriteExistingJobs(true); // 延时启动定时任务,避免系统未完全启动却开始执行定时任务的情况 bean.setStartupDelay(15); // 注册触发器 bean.setTriggers(myFirstExerciseJobTrigger, mySecondExerciseJobTrigger); return bean; } }
Quartz的其他扩展(待更新)
多线程下的Quartz
Job仓库
Job的Param
//TODO