start(); 开启
standby(); 挂起,可以使用start()再次开启
shutdown(); 完全关闭scheduler,不可以被start()所开启
调度器:Scheduler
任务:Job和JobDetail
触发器:Trigger
通配符说明
“/”是每的意思 0/5就是表达每五秒钟 “,”是“或”的关系 14,18表示14点和18点
这里的L 代表最后 last 所以6L表示最后的星期五
这里的#号是第的意思,6代表的是星期五 6#3 表示的是 第三周的星期五
这里的年可以缺省,就可以不写
这里的cron表达式中的*代表“每X”,如这里的* * *。。是每秒每分每小时这样的
Quartz用到的设计模式
链式编码?
job、trigger、scheduler
通配符说明
cron tigger
请问为什么是先启动再绑定,感觉不符合逻辑啊
Quartz与Spring整合(前提搭建好Spring环境)
步骤1:pom文件引入jar包,Quartz需要使用Spring的上下文。它还需要使用到Spring的事物。其次就是Quartz的jar包了。
Spring结合Quartz实现定时任务:
方式一:MethodInvokingJobDetailFactoryBean适合调用特定bean方法时很方便。
如图:MethodInvokingJobDetailFactoryBean可以通过dispatcherServlet.xml进行配置,通过它就可以创建JobDetail,其中myBean相当于实现定时任务的类,注入的printMessage为定时任务的方法名。之后再结合Trigger就可以实现定时的执行。
方式二:JobDetailFactoryBean支持传入一些参数。
定时任务的配置形式(声明式的配置,因为这样可以简化代码的实现,这样就可以将配置信息与代码相分离,便于程序的维护)
StdScheduler是通过读取quartz.properties配置文件信息进行加载的。
quartz.properties的位置和加载顺序:默认情况下Quartz运行时加载的是工程目录下的quartz.properties,如果工程目录下没有quartz.properties,那么就会到Quartz的jar包中去加载quartz.properties配置文件。
如图:工程目录中没有quartz.properties文件情况。
举例:自定义quartz.properties配置文件,并放置项目工程目录的根目录下,通过修改线程池中线程数量为-1,验证了加载的是工程目录中的配置文件。
quartz.properties配置文件的组成:stdScheduler在启动时,就会加载该配置文件,参考该配置文件进行初始化。
1、调度器属性
2、线程池属性:关系到Quartz后台处理能力的性能。
threadCount:Quartz创建的线程用来处理定时任务的业务,最少为1,它没有限制,并且没有默认值,但出于资源的有限考虑,适量即可。
threadPriority:设置工作线程的优先级,优先级大优先执行它的定时任务,它的最大值为10,最小值为1,正常情况下设置为5,5也是默认值,集群中会用到它。
org.quartz.threadPool.class
3、作业存储设置
4、插件配置
Scheduler:通过工厂模式创建的,如图,SchedulerFactory的实现类有两个,常用的是StdSchedulerFactory。
Job和Trigger的关系:如图。
Scheduler的创建方式:如图。
接下来主要讲解StdSchedulerFactory,因为DirectSchedulerFactory的参数都需要代码去实现的(开发中提倡声明式配置,就是在配置文件中进行配置,例如xml中等)。
StdSchedulerFactory:使用一组参数(Java.util.Properties)来创建和初始化Quartz调度器,其中这组参数就包括了指定后台运行Quartz的线程数。还有Job的信息存储在何种介质中(例如内存中、或者数数据库中),配置参数一般存储在quartz.properties中。StdSchedulerFactory通过getScheduler犯法来创建和初始化调度器对象。
Scheduler的主要函数:
Date scheduleJob(JobDetail jobDetail,Trigger trigger):绑定JobDetail和Trigger,将其注入到Scheduler,其中返回的Date表示即将执行的最近一次的执行时间,如图。
void start():它是用来启动Scheduler调度器,指定定时任务的。
void standby():Scheduler暂时挂起,暂停工作。停止之后可以再通过start方法重新启动。
void shutdown():关闭调度器,不可以重新启动了。
注意:shutdown支持传入一个布尔类型的参数,如果传入的为true,就表示等待所有正在执行j的job执行完毕后,再进行关闭scheduler。如果传入的false,那么就和无参数一样,表示直接关闭scheduler。
举例:shutdown(true),如图。
CronTrigger的作用:基于日历的触发器,而不是像SimpleTrigger精确到指定间隔时间,它比SimpleTrigger更常用(例如:每月的1号执行定时任务,这是SimpleTrigger实现不了的)。
Cron表达式:CronTrigger是基于Cron表达式实现的,如图。
举例:通过CronTrigger实现每秒钟实现一次定时任务。
Cron表达式:使用规则如下图(","表示或的意思,"-"表示至的意思,"*”表示所有的意思,"/"表示每的意思,"?"表示任意的意思,“#”表示第的意思。
Cron表达式举例:如图。
注意:
日和周不能是同一个值(不能同时是*或者?)
月和周的英文不区分大小写,
周X是(X+1),周日是1
作业:
SimpleTrigger的作用:在指定时间执行且仅执行一次任务,或者是在指定时间间隔内多次执行任务。
举例1:当前时间4秒后,执行定时任务并仅执行一次。
举例2:每隔2秒钟执行一次定时任务,通过withRepeatCount方法实现重复执行定时任务,如果withRepeatCount参数是整数,代表第一次执行之后执行定时任务的次数,如图。
注意:endAt方法优先级大于withRepeatCount方法优先级,即使次数还没执行完,到指定时间也会结束。
Trigger定义:Quartz的触发器,用来定义调度程序任务执行的时间,也就是触发执行Job的时间。
Quartz框架中的Trigger架构:如图。
1、Trigger是Builder设计模式创建的。
2、Trigger实现类很多,这里常用CronTriggerImpl和SimpleTriggerImpl这两个Trigger实现类。
触发器通用属性(所有实现类拥有的属性)
JobKey:Job实例的标识,触发器触发调度工具时,该Job对应的相应任务就会执行(通过JobKey可以获取和Trigger绑定的JobDetail的一些信息)。
StartTime:触发器的时间表,首次被触发的时间,类型为Java.uitl.Date(可以在调度器中存储一个触发器,当时间到了触发的时间调度器就会调用Job的相应任务)。
EndTime:触发器不再被触发的时间,它的类型为Java.uitl.Date,超过这个时间,触发器就会执行了。
举例:如图,演示startTime、endTime、JobKey的使用。
1、通过Date获取3秒后的时间。
2、触发器执行指定触发时间的方法(startAt()、endAt())
3、通过Trigger获取JobKey,并且通过jobKey获取与Trigger绑定的Job的JobDetail的相关信息。
4、通过Trigger获取startTime和endTime的信息。
举例:如图。
知识点1:可以通过getMergedJobDataMap()获取JobDetail和Trigger合并的JobDataMap。但这里需要注意一点是如果Trigger和JobDetail的key相同,那么Trigger会覆盖JobDetail。
第二种获取传入JobExecuteContext的参数:更直接,更简洁。通过setter方法直接对Job里对应key值的成员变量赋值。
举例:如图。
知识点1:通过在实现Job接口的实现类中,定义成员变量并提供setter方法,前提成员变量的类型要和传入的value值类型相同,名称要和key的名称相同。该种方式就可以不使用JobDataMap了。
JobExecutionContext:它是位于Job接口的execute方法的参数位置。由于每个业务逻辑Job实例需要的参数不同,Quartz没办法提供带有参数的构造函数。去给Job实例初始化参数。因此Quartz在每次执行Job时,都需要重新创建一个Job实例。并通过newInstance的反射机制调用无参构造函数,依据Job实现类的描述来实例化Job。所以想进行传参就需要使用JobExecutionContext。(类似于Servlet访问ServletContext那样)通过JobExecutionContext,Job可以访问到所处环境的所有信息(包括注射到Scheduler上与该Job相关的JobDetail和Trigger)。
JobDataMap:它支持键值对的形式,将自定义参数传入JobDataMap。
获取JobDataMap:
举例:如图。
知识点1:通过在创建JobDetail或者Trigger时,通过usingJobData(参数1,参数2)为JobExecuteContext参数传入参数,如果传入多个参数,可以通过定义多个usingJobData方法。
知识点2:可以通过JobKey或者TriggerKey实例的getName或者getGroup方法获取JobDetail或者Trigger的唯一标识和组。而JobKey或者TriggerKey是通过JobExecuteContext参数的getJobDetail.getKey()或者getTriiger().getKey()方法获取的。
知识点3:可以通过JobDataMap获取传入的参数,也就是通过传入的key获取value,而JobDataMap是通过JobExecuteContext实例的getJobDetail.getJobDataMap或者getTrigger.getJobDataMap获取的。之后就可以通过JobDataMap实例的getKey("key")获取值。
Job接口:实现业务逻辑的任务接口,实现该接口需要实现execute方法,该方法类似于TimerTask的run方法。JobExecutionContext参数是Job执行的上下文,其中在该参数中有一个JobDataMap,它包含了输入的参数。
注意:execute方法声明抛出了一个异常,如果任务执行失败,我们可以通过捕获该异常来处理。避免了Timer的全崩式失败。
Job在Quartz的生命周期:每次Scheduler执行Job时,它在调用execute方法前会根据JobDetail提供的类型创建一个Job实例。当该任务执行完毕后,会丢弃该Job实例,并且释放的实例会被垃圾回收机制回收。
JobDetail接口:JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存储特定Job实例的状态信息,Scheduler需要借助JobDetail对象来添加Job实例。
Job的重要属性:
name:任务的名称,它在JobDetail中是必须项。
group:任务所在组,默认值是大写的DEFAULT,它也是必须项。
jobClass:JobDetail传入任务的类类型,它也是必须项。
jobDataMap:它用来传参的作用。
使用场景:例如,输出日志,输出执行的任务所在路径就可以通过getClass()。
举例:任务每隔两秒钟打印一次Hello World。
首先,需要到maven中央仓库复制坐标到pom文件中,如图。
——总结——
JobDetail:
通过它可以获取Job执行时的一些信息。JobDetail它是通过Builder设计模式创建的。
Trigger:
通过它可以触发Job何时执行。它也是通过Builder设计模式创建的。立即执行是通过startNow方法。时间间隔通过withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2)。重复执行repeatForever()。
Scheduler:它是通过Factory设计模式创建的。