Quartz 学习和使用
介绍
Quartz 是一个完全使用java编写的开源作业调度框架,为在java应用程序中进行作业调度提供了简单却强大的机制。同时Quartz还有强大的调度功能,支持持久化,能够并发的执行任务,还可以对任务进行监听,集群等特性。
Quartz 设计的核心类包括 Scheduler(调度器), Job(定时任务),JobDetail(任务详情) 以及 Trigger(触发器)。其中,Job负责定义需要执行的任务,就是说这个定时任务具体要干的事情;JobDetail定义任务任务的详细信息,例如任务具体对应的类,是否是持久化,是否并发等信息;Trigger 负责设置调度策略即什么时间执行定时任务;Scheduler 将JobDetail和Trigger二者组装在一起,统一调度任务。因此配置一个定时任务,需要将这四个一起配置上。
Quartz 特性
- 强大的调度功能。例如支持丰富多样的调度方法,我们既可以使用SimpleTriggerFactoryBean进行时间间隔对定时任务的控制,还可以使用CronTriggerFactoryBean配置cron表达式满足各种常规及特殊需求,具体的可以参考例子触发器的配置
- 并发调度。例如一个定时任务是10秒钟执行一次,用了30秒执行完毕,当到了它下一次执行的时间的时候,它会继续执行,而不会说等待上一个任务结束后执行。具体可以参考并发调度例子。需要注意的是,只有无状态的任务才会并发执行,有状态的任务,同一时间只能有一个。要想一个任务变成有状态的,只需要加上注解@DisallowConcurrentExecution就可以了,具体的参考不并发调度例子
- 持久化。Quartz默认是使用内存存储,速度比较快,但是每次重启程序之后Job的信息会丢失,Quartz还可以支持数据库存储,相对于内存存储会慢点,但是Job的信息不会丢失,每次重启程序之后能够按照之前的Job信息继续执行Job
- 定时任务的监听。Quartz提供了listener功能,主要包含三种 listener:JobListener,TriggerListener以及 SchedulerListener,通过实现监听类,在系统发生故障的时候能够及时的发送邮件通知相关的人员,以JobListener为例,具体查看JobListener例子
- 集群。Quartz 是通过共享一个数据库达到集群的效果的,而且还能够进行故障转移,检测到某一个服务失败之后自动使用另外的服务。
简单quartz Demo
我们这里采用maven项目,整合spring来实现这个quartz项目,用这个定时任务每10秒打印一次时间。
- 首先我们需要一个带有spring的maven项目,这个大家没有的可以百度学习下。
然后我们需要下载jar包,因为使用maven项目,所以这里我们只需要加上对应jar包的xml配置就可以了,这个我们在Quartz的官网首页可以找的到。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>
编写对应的定时任务类。
- 需要继承org.springframework.scheduling.quartz.QuartzJobBean类,并重写executeInternal方法,代码如下。
import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; /** * spring 整合quartz 的demo<br> * 每10秒中打印一次时间 * * @author zxr * @date 2017年2月8日 下午1:59:18 */ public class HelloQuartz extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(sdf.format(new Date())); } }
- 不继承对应的类,也是可以使用quartz进行调用的
import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.stereotype.Component; /** * spring 整合quartz 的demo2<br> * 每10秒中打印一次时间 * * @author zxr * @date 2017年2月8日 下午1:59:18 */ @Component("helloQuartz2") public class HelloQuartz2 { public void printDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Demo2:" + sdf.format(new Date())); } }
在xml中配置对定时任务作业和对应的触发器方式进行配置。每次新建一个定时任务的时候,都需要在xml中进行作业的配置和对应的触发器的配置。
对作业进行配置
- 使用JobDetailFactoryBean,这种的jobClass需要继承QuartzJobBean,调用的是固定的方法executeInternal。同时还可以使用jobDataMap传递数据。
<bean name="helloQuartz" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <!-- 作业对应的类 --> <property name="jobClass" value="com.shxzhlxrr.quartz.HelloQuartz" /> <!-- 是否是持久性的 --> <property name="durability" value="true" /> </bean>
- 使用MethodInvokingJobDetailFactoryBean,这种是想要调用特定Bean的某个方法的时候比较方便。(这种方式不推荐使用,因为这种方式不支持持久化)
<bean id="helloQuartzBean2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" > <property name="targetObject" ref="helloQuartz2" /> <property name="targetMethod" value="printDate" /> </bean>
对触发器进行配置
- 当是需要间隔某个时间段执行的时候,可以使用该配置。
<bean id="helloQuartzTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="helloQuartz" /> <!-- 表示系统启动之后,延迟一秒启动 --> <property name="startDelay" value="1000" /> <!-- 表示每10秒执行一次 --> <property name="repeatInterval" value="10000" /> </bean>
- 当需要更加详细的灵活的配置的时候,可以使用该配置。
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="helloQuartzBean2" /> <property name="cronExpression" value="0/10 * * ? * *" /> </bean>
配置调度器,将JobDetails和Triggers整合到一起进行。
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 作业详情 --> <property name="jobDetails"> <list> <ref bean="helloQuartz" /> <ref bean="helloQuartzBean2" /> </list> </property> <!-- 触发器 --> <property name="triggers"> <list> <ref bean="helloQuartzTrigger" /> <ref bean="helloQuartzTrigger2" /> </list> </property> </bean>
看完了如果有什么问题可以留言,一起交流,共同进步!