Quartz 使用
Quartz 核心:調度器Scheduler
,任務JobDetail
,觸發器Trigger
調度器 Scheduler
Scheduler 接口爲任務的調度者,相當於一個總指揮,由工廠模式(SchedulerFactory接口)創建,
SchedulerFactory接口有2個實現類:StdSchedulerFactory 和 DirectSchedulerFactory。
通常通過 StdSchedulerFactory實例的getScheduler()
方法創建調度器。
SchedulerFactory schedulerFactory =new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start(); //開啓任務
scheduler.scheduleJob(jobDetail, trigger1);
任務 JobDetail
JobDetail是具體Job任務的包裝,包含一些描述信息和傳遞一些參數設置。
在設置自己的任務的時候需要實現Job
接口:
package org.quartz;
public interface Job {
void execute(JobExecutionContext var1) throws JobExecutionException;
}
JobExecutionContext
是任務執行的上下文對象,包含所有執行過程中的配置,類似於ServletContext容器
實現execute
方法爲具體的任務邏輯。
public class HelloQuartz implements Job{
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
System.out.println("hello quartz at :" + sf.format(date));
}
}
使用JobDetail
對 Job進行包裝,設置執行參數,如執行週期,分組,標識,要執行的任務等
JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
.withIdentity("hello_job", "hello_group")
.build();
觸發器 Trigger
SimpleTrigger 和 CronTrigger,SimpleTrigger設置一些簡單的條件,CronTrigger才能體現Quartz的強大之處。
SimpleTrigger作用:
在一個指定的時間段內執行一次作業
或是在指定的時間間隔內多次執行作業任務
示例:
任務:
public class HelloQuartz implements Job{
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
System.out.println("hello quartz at :" + sf.format(date));
}
}
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException, InterruptedException {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
System.out.println("current time is:" + sf.format(date));
JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
.withIdentity("hello_job", "hello_group")
.build();
// TODO 1)在一個指定的時間段內執行一次作業
//設置距離當前時間4秒後執行,切僅執行一次, 無scheduler.shutdown()
date.setTime(date.getTime() + 4000L);
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity("hello_trigger")
.startAt(date)
.build();
// TODO 2)在指定的時間間隔內多次執行作業任務
//設置在4秒後執行,每隔2秒執行一次,執行4次,並且在6秒後結束執行
//注意:一旦設置了 endAt 結束時間,到達時間時就會結束,剩餘次數不會執行
Date endTime = new Date();
endTime.setTime(endTime.getTime() + 6000L);
SimpleTrigger trigger1 =(SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity("trigger1")
.startAt(date)
.endAt(endTime)
.withSchedule(SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.withRepeatCount(4))
.build();
SchedulerFactory schedulerFactory =new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail, trigger1);
}
}
如圖,重複2次之後結束,因爲到達了endAt 指定時間
CronTrigger作用
基於日曆的作業調度器,不是像SimpleTrigger那樣精確指定間隔時間,更常用。
Cron表達式
用於配置CronTrigger 實例
由7個子表達式組成字符串
格式:[秒] [分] [小時] [日] [月] [周] [年]
Cron表達式提示:
- ‘L’和’W’可以一組使用
比如:在日設置上,表示最後一個工作日(發工資?)
- 周字段英文不區分大小寫
- 在線工具生成Cron表達式
Spring 與 Quartz 的整合
- 添加maven依賴:
<!-- 其他省略-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
- 配置quartz 任務的2種方式:
任務類一:
@Component("myBean")
public class MyBean {
public void printMessage(){
System.out.println("msssssssss..");
}
}
任務類二:
@Component("anotherBean")
public class AnotherBean {
public void printAnotherMessage() {
System.out.println("AnotherMessage");
}
}
任務類二注入的job:
public class FirstScheduledJob extends QuartzJobBean {
private AnotherBean anotherBean;
public void setAnotherBean(AnotherBean anotherBean){
this.anotherBean = anotherBean;
}
@Override
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("FirstScheduledJob Executes!" + sf.format(date));
this.anotherBean.printAnotherMessage();
}
}
xml 配置:
<!-- 1)配置quartz 作業方式一:使用MethodInvokingJobDetailFactoryBean-->
<bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myBean" />
<property name="targetMethod" value="printMessage" />
</bean>
<!-- 距離當前時間1秒之後執行,之後每隔兩秒鐘執行一次 -->
<bean id="mySimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="simpleJobDetail"/>
<property name="startDelay" value="1000"/>
<property name="repeatInterval" value="2000"/>
</bean>
<!-- 2)配置quartz 作業方式二:使用JobDetailFactoryBean-->
<bean id="firstComplexJobDetail"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass"
value="com.kay.quartz.FirstScheduledJob" />
<property name="jobDataMap">
<map>
<entry key="anotherBean" value-ref="anotherBean" />
</map>
</property>
<!-- job沒有綁定trigger 仍然保留在Scheduler中-->
<property name="Durability" value="true"/>
</bean>
<!-- 每隔5秒鐘執行一次 -->
<bean id="myCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="firstComplexJobDetail"/>
<property name="cronExpression" value="0/5 * * ? * *"/>
</bean>
<!-- 最後交給Scheduler 進行調度-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="simpleJobDetail"/>
<ref bean="firstComplexJobDetail"/>
</list>
</property>
<property name="triggers">
<list>
<ref bean="mySimpleTrigger"/>
<ref bean="myCronTrigger"/>
</list>
</property>
</bean>
2種方式比較:
MethodInvokingJobDetailFactoryBean
配置簡單,使用方便JobDetailFactoryBean
傳遞數據等,更加靈活,jobClass
的類要繼承QuartzJobBean
附:quartz.properties 配置文件
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# ===========================================================================
# Configure Main Scheduler Properties 調度器屬性
# ===========================================================================
org.quartz.scheduler.instanceName= DefaultQuartzScheduler
org.quartz.scheduler.instanceid=AUTO
org.quartz.scheduler.rmi.export= false
org.quartz.scheduler.rmi.proxy= false
org.quartz.scheduler.wrapJobExecutionInUserTransaction= false
# ===========================================================================
# Configure ThreadPool 線程池屬性
# ===========================================================================
#線程池的實現類(一般使用SimpleThreadPool即可滿足幾乎所有用戶的需求)
org.quartz.threadPool.class= org.quartz.simpl.SimpleThreadPool
#指定線程數,至少爲1(無默認值)(一般設置爲1-100直接的整數合適)
org.quartz.threadPool.threadCount= 10
#設置線程的優先級(最大爲java.lang.Thread.MAX_PRIORITY 10,最小爲Thread.MIN_PRIORITY 1,默認爲5)
org.quartz.threadPool.threadPriority= 5
#設置SimpleThreadPool的一些屬性
#設置是否爲守護線程
#org.quartz.threadpool.makethreadsdaemons = false
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread= true
#org.quartz.threadpool.threadsinheritgroupofinitializingthread=false
#線程前綴默認值是:[Scheduler Name]_Worker
#org.quartz.threadpool.threadnameprefix=swhJobThead;
# 配置全局監聽(TriggerListener,JobListener) 則應用程序可以接收和執行 預定的事件通知
# ===========================================================================
# Configuring a Global TriggerListener 配置全局的Trigger監聽器
# MyTriggerListenerClass 類必須有一個無參數的構造函數,和 屬性的set方法,目前2.2.x只支持原始數據類型的值(包括字符串)
# ===========================================================================
#org.quartz.triggerListener.NAME.class = com.swh.MyTriggerListenerClass
#org.quartz.triggerListener.NAME.propName = propValue
#org.quartz.triggerListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configuring a Global JobListener 配置全局的Job監聽器
# MyJobListenerClass 類必須有一個無參數的構造函數,和 屬性的set方法,目前2.2.x只支持原始數據類型的值(包括字符串)
# ===========================================================================
#org.quartz.jobListener.NAME.class = com.swh.MyJobListenerClass
#org.quartz.jobListener.NAME.propName = propValue
#org.quartz.jobListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configure JobStore 存儲調度信息(工作,觸發器和日曆等)
# ===========================================================================
# 信息保存時間 默認值60秒
org.quartz.jobStore.misfireThreshold= 60000
#保存job和Trigger的狀態信息到內存中的類
org.quartz.jobStore.class= org.quartz.simpl.RAMJobStore
# ===========================================================================
# Configure SchedulerPlugins 插件屬性 配置
# ===========================================================================
# 自定義插件
#org.quartz.plugin.NAME.class = com.swh.MyPluginClass
#org.quartz.plugin.NAME.propName = propValue
#org.quartz.plugin.NAME.prop2Name = prop2Value
#配置trigger執行歷史日誌(可以看到類的文檔和參數列表)
#org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
#org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at= {4, date, HH=mm=ss MM/dd/yyyy}
#org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH=mm=ss MM/dd/yyyy} with resulting trigger instruction code= {9}
#配置job調度插件 quartz_jobs(jobs and triggers內容)的XML文檔
#加載 Job 和 Trigger 信息的類 (1.8之前用:org.quartz.plugins.xml.JobInitializationPlugin)
#org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
#指定存放調度器(Job 和 Trigger)信息的xml文件,默認是classpath下quartz_jobs.xml
#org.quartz.plugin.jobInitializer.fileNames = my_quartz_job2.xml
#org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
#org.quartz.plugin.jobInitializer.failOnFileNotFound = true
#自動掃描任務單並發現改動的時間間隔,單位爲秒
#org.quartz.plugin.jobInitializer.scanInterval = 10
#覆蓋任務調度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情況
#org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
# ===========================================================================
# Sample configuration of ShutdownHookPlugin ShutdownHookPlugin插件的配置樣例
# ===========================================================================
#org.quartz.plugin.shutdownhook.class = \org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true
#
# Configure RMI Settings 遠程服務調用配置
#
#如果你想quartz-scheduler出口本身通過RMI作爲服務器,然後設置“出口”標誌true(默認值爲false)。
#org.quartz.scheduler.rmi.export = false
#主機上rmi註冊表(默認值localhost)
#org.quartz.scheduler.rmi.registryhost = localhost
#註冊監聽端口號(默認值1099)
#org.quartz.scheduler.rmi.registryport = 1099
#創建rmi註冊,false/never:如果你已經有一個在運行或不想進行創建註冊
# true/as_needed=第一次嘗試使用現有的註冊,然後再回來進行創建
# always=先進行創建一個註冊,然後再使用回來使用註冊
#org.quartz.scheduler.rmi.createregistry = never
#Quartz Scheduler服務端端口,默認是隨機分配RMI註冊表
#org.quartz.scheduler.rmi.serverport = 1098
#true=鏈接遠程服務調度(客戶端),這個也要指定registryhost和registryport,默認爲false
# 如果export和proxy同時指定爲true,則export的設置將被忽略
#org.quartz.scheduler.rmi.proxy = false