日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

调度器Quartz的简述与使用总结

發(fā)布時間:2024/9/21 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 调度器Quartz的简述与使用总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

Quartz是一款性能強(qiáng)大的定時任務(wù)調(diào)度器。開發(fā)人員可以使用Quartz讓任務(wù)在特定時間特定階段進(jìn)行運(yùn)行。比如對特定類型新聞或股指期貨指數(shù)等內(nèi)容的爬取,可以編寫爬蟲程序然后使用Quartz在后臺指定特定時間點(diǎn)對任務(wù)進(jìn)行執(zhí)行,來自動收集信息。大型系統(tǒng)間數(shù)據(jù)的按時批量導(dǎo)入任務(wù)也可由Quartz進(jìn)行調(diào)度。Quartz提供兩種類型的任務(wù)觸發(fā)方式,一種是按指定時間間隔觸發(fā)任務(wù),另一種是按指定日歷時間觸發(fā)任務(wù)。下面將對Quartz進(jìn)行詳細(xì)介紹。

?

一、Hello Quartz

??下面首先實(shí)現(xiàn)一個簡單實(shí)例。?
新建maven項(xiàng)目,在pom.xml導(dǎo)入Quartz的jar包:

<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version> </dependency>

定義HelloJob類,實(shí)現(xiàn)Job接口并定義具體的任務(wù)邏輯。

public class HelloJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("hello");} }

實(shí)例化Scheduler、Triggle和Job對象,并執(zhí)行定時任務(wù)。

public class QuartzConsole {public static void main(String[] args) throws SchedulerException {SchedulerFactory factory=new org.quartz.impl.StdSchedulerFactory();Scheduler scheduler=factory.getScheduler();//通過SchedulerFactory實(shí)例化Scheduler對象scheduler.start();JobDetail job=newJob(HelloJob.class)//指定Job的運(yùn)行類.withIdentity("myJob","group1").build();// name "myJob", group "group1"兩個變量作為一個job的keyTrigger trigger=newTrigger().withIdentity("myTrigger","group1")// name "myTrigger", group "group1" 兩個變量作為一個trigger的key.startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5).repeatForever())//定義任務(wù)觸發(fā)方式,每5秒執(zhí)行一次,一直重復(fù)。.build();scheduler.scheduleJob(job,trigger);} }

運(yùn)行程序每5秒執(zhí)行一次Job。?
??Quartz通過Job、Triggle和Schedule實(shí)現(xiàn)任務(wù)的調(diào)度。三者關(guān)系如圖所示。

??Job定義:開發(fā)者實(shí)現(xiàn)Job接口,重寫execute()方法定義具體Job實(shí)現(xiàn)。JobDetail接口定義一個job的相關(guān)配置細(xì)節(jié)。通過JobBuilder構(gòu)建一個實(shí)現(xiàn)JobDetail接口的JobDetailImpl類,傳入Scheduler對象。?
??**Triggle定義:**Triggle有兩種觸發(fā)器實(shí)現(xiàn),SimpleTriggle按指定時間間隔進(jìn)行觸發(fā),CronTriggle按指定日歷時間進(jìn)行觸發(fā)。Triggle接口同Job類似定義了觸發(fā)器的具體配置細(xì)節(jié),由TriggleBuilder構(gòu)建觸發(fā)器實(shí)例。?
??**Scheduler定義:**Scheduler調(diào)度器由SchedulerFactory產(chǎn)生,start()方法定義schedule的執(zhí)行,將實(shí)例化的Job和Triggle對象作為scheduleJob()的入?yún)?#xff0c;由該方法執(zhí)行具體任務(wù)的觸發(fā)執(zhí)行。

二、SimpleTriggle和CronTriggle觸發(fā)器。

??SimTriggle觸發(fā)器可以指定某一個任務(wù)在一個特定時刻執(zhí)行一次,或者在某一時刻開始執(zhí)行然后重復(fù)若干次。?
??SimpleTriggle的代碼實(shí)現(xiàn)如下。

public class SimpleTriggerJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("Hello SimpleTriggerJob -- "+df.format(new Date()));} }
  • ?
//SimpleTrigger觸發(fā)器按指定時間間隔調(diào)度任務(wù) public class SimpleTriggerTester {public static void main(String[] args) throws SchedulerException {JobDetail jobDetail=newJob(SimpleTriggerJob.class).withIdentity("simpleTriggerJob","group1").build();//未來5秒后執(zhí)行一次 // SimpleTrigger trigger=(SimpleTrigger) newTrigger() // .withIdentity("simpleTrigger","group1") // .startAt(futureDate(5, DateBuilder.IntervalUnit.SECOND)) // .forJob("simpleTriggerJob","group1") // .build();//從特定時間開始,然后每隔十秒執(zhí)行1次,重復(fù)3次: // SimpleTrigger trigger=(SimpleTrigger) newTrigger() // .withIdentity("simpleTrigger","group1") // .startAt(dateOf(18,11,40)) // .withSchedule(simpleSchedule() // .withIntervalInSeconds(10) // .withRepeatCount(3)) // .forJob("simpleTriggerJob","group1") // .build();//在每分鐘開始時執(zhí)行,每分鐘執(zhí)行一次,永遠(yuǎn)重復(fù),直到指定時間點(diǎn)停止SimpleTrigger trigger=(SimpleTrigger) newTrigger().withIdentity("simpleTrigger","group1").startAt(evenMinuteDate(null)).withSchedule(simpleSchedule().withIntervalInMinutes(1).repeatForever()).endAt(dateOf(18,22,0)).forJob("simpleTriggerJob","group1").build();SchedulerFactory factory=new StdSchedulerFactory();Scheduler scheduler=factory.getScheduler();scheduler.start();scheduler.scheduleJob(jobDetail,trigger);} }

??CronTriggle觸發(fā)器作用范圍更廣,它是基于日歷的概念而不是像SimpleTriggle觸發(fā)器基于較短的一段特定時間間隔。?
例如:可以使用CronTriggle觸發(fā)器,指定任務(wù)在每個周五晚上7點(diǎn)執(zhí)行一次;在每個月的倒數(shù)第二天早上7點(diǎn)執(zhí)行三次;按照時區(qū)的變換對任務(wù)運(yùn)行進(jìn)行動態(tài)調(diào)整。?
通過向cronSchedule()構(gòu)造方法傳遞特定格式字符串配置任務(wù)的執(zhí)行。?
字符串格式如“Seconds Minutes Hours Day-of-Month Month Day-of-Week Year”?
例如:?
“0 30 10-12 ? * WED,FRI”表示每周三和周五的10:30,11:30,12:30各執(zhí)行一次?
“0 0/30 8-9 5,20 * ?”表示每個月第五天和第二十天的8點(diǎn)、9點(diǎn)每半個小時執(zhí)行一次。?
取值范圍:?
Seconds:0-60?
Minutes :0-60?
Hours:0-23?
Day-of-Month:1-31?
Month:1-12?
Day-of-Week:1-7或SUN, MON, TUE, WED, THU, FRI 和SAT.?
“-”可代表從A到B時間段?
“/”代表一個遞增時間,A/B指在當(dāng)前的時間域,從A開始每B個當(dāng)前時間單位執(zhí)行一次,等價于在該時間域的第A,A+B,A+2B…時刻各觸發(fā)任務(wù)一次。?
“?”用于day-of-month和day-of-week時間域,表示沒有特別的設(shè)置。?
“L”用于day-of-month和day-of-week時間域,指定每個月或每周的倒數(shù)第n天。day-of-month的“6L”或者“FRIL”代表每個月的最后一個周五。“L-3”代表從每個月的第三天到最后一天。?
“A#B”在day-of-week時間域代表每個月的第B周的星期A。?
??CronTriggle的代碼實(shí)現(xiàn)如下。?
“*”在時間域上代表“每個”或者無限重復(fù)的意思。?
CronTrigger實(shí)例代碼如下:

//CronTrigger按指定日歷時間運(yùn)行job // cronSchedule("_ _ _ _ _ _") 方法的6個參數(shù)代表的含義 // Seconds // Minutes // Hours // Day-of-Month // Month // Day-of-Week // Year (optional field) // 具體參數(shù)設(shè)置見http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-06.htmlpublic class CronTriggerTester {public static void main(String[] args) throws SchedulerException {JobDetail jobDetail=newJob(CronTriggerJob.class).withIdentity("CronTriggerJob","group1").build();//每天的指定小時分鐘點(diǎn)執(zhí)行一次 // Trigger trigger=newTrigger() // .withIdentity("CronTrigger","group1") // .forJob("CronTriggerJob","group1") // .withSchedule(dailyAtHourAndMinute(19,7)) // .build();//每周日每分鐘的第五秒開始執(zhí)行,每5秒執(zhí)行一次 // Trigger trigger=newTrigger() // .withIdentity("CronTrigger","group1") // .forJob("CronTriggerJob","group1") // .withSchedule(cronSchedule("0/5 * * ? * 1")) // .build();//按指定時區(qū)的時間執(zhí)行Trigger trigger=newTrigger().withIdentity("CronTrigger","group1").forJob("CronTriggerJob","group1").withSchedule(dailyAtHourAndMinute(19,23).inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))).build();SchedulerFactory factory=new StdSchedulerFactory();Scheduler scheduler= factory.getScheduler();scheduler.scheduleJob(jobDetail,trigger);scheduler.start();} }
  • ?

三、Listeners ——TriggerListeners、JobListeners和SchedulerListeners

??監(jiān)聽器用來對Job、Trigger和Schedule運(yùn)行過程中的所處的運(yùn)行狀態(tài)和運(yùn)行行為進(jìn)行監(jiān)聽。TriggerListeners、JobListeners和SchedulerListeners分別為一組接口。實(shí)現(xiàn)接口并重寫接口方法,實(shí)現(xiàn)對監(jiān)聽器的定制化開發(fā)。 然后通過ListenerManager對監(jiān)聽器進(jìn)行注冊。?
關(guān)于監(jiān)聽器的實(shí)例代碼如下:?
??定制化的JobListner類:

public class MyJobListener implements JobListener{@Overridepublic String getName() {return "jobListener name is MyJobListener";}@Overridepublic void jobToBeExecuted(JobExecutionContext context) {System.out.println("當(dāng)前任務(wù)將要執(zhí)行。");}@Override public void jobExecutionVetoed(JobExecutionContext context) {System.out.println("當(dāng)前任務(wù)執(zhí)行被否決。");}@Override public void jobWasExecuted(JobExecutionContext context,JobExecutionException jobException) {System.out.println("當(dāng)前任務(wù)執(zhí)行完畢。");} }
  • ?

??定制化的TriggerListener類:

public class MyTriggerListener implements TriggerListener {@Override public String getName() {return "TriggerListener name is MyTriggerListener";}@Override public void triggerFired(Trigger trigger, JobExecutionContext context) {System.out.println("觸發(fā)器正在觸發(fā)");}@Override public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {return false;}@Override public void triggerMisfired(Trigger trigger) {System.out.println("觸發(fā)器錯過觸發(fā)");}@Override public void triggerComplete(Trigger trigger, JobExecutionContext context,Trigger.CompletedExecutionInstruction triggerInstructionCode) {System.out.println("觸發(fā)器觸發(fā)完畢");} }
  • ?

??定制化的SchedulerListener類:

public class MySchedulerListener implements SchedulerListener {@Override public void jobScheduled(Trigger trigger) {System.out.println("jobScheduled");}@Override public void jobUnscheduled(TriggerKey triggerKey) {System.out.println("jobScheduled");}@Override public void triggerFinalized(Trigger trigger) {System.out.println("triggerFinalized");}@Override public void triggerPaused(TriggerKey triggerKey) {System.out.println("triggerPaused");}@Override public void triggersPaused(String triggerGroup) {System.out.println("triggersPaused");}@Override public void triggerResumed(TriggerKey triggerKey) {System.out.println("triggerResumed");}@Override public void triggersResumed(String triggerGroup) {System.out.println("triggersResumed");}@Override public void jobAdded(JobDetail jobDetail) {System.out.println("jobAdded");}@Override public void jobDeleted(JobKey jobKey) {System.out.println("jobDeleted");}@Override public void jobPaused(JobKey jobKey) {System.out.println("jobPaused");}@Override public void jobsPaused(String jobGroup) {System.out.println("jobsPaused");}@Override public void jobResumed(JobKey jobKey) {System.out.println("jobResumed");}@Override public void jobsResumed(String jobGroup) {System.out.println("jobsResumed");}@Override public void schedulerError(String msg, SchedulerException cause) {System.out.println("schedulerError");}@Override public void schedulerInStandbyMode() {System.out.println("schedulerInStandbyMode");}@Override public void schedulerStarted() {System.out.println("schedulerStarted");}@Override public void schedulerStarting() {System.out.println("schedulerStarting");}@Override public void schedulerShutdown() {System.out.println("schedulerShutdown");}@Override public void schedulerShuttingdown() {System.out.println("schedulerShuttingdown");}@Override public void schedulingDataCleared() {System.out.println("schedulingDataCleared");} }
  • ?

??監(jiān)聽器測試類,Job使用HelloQuartz一節(jié)中的HelloJob類:

public class ListenerTester {public static void main(String[] args) throws SchedulerException {//初始化調(diào)度器SchedulerFactory factory=new StdSchedulerFactory();Scheduler scheduler=factory.getScheduler();JobDetail jobDetail=newJob(HelloJob.class).withIdentity("printerJob","group2").build();Trigger trigger=newTrigger().withIdentity("jobListenerTrigger","group2").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5)).build();//實(shí)例化監(jiān)聽器對象MyJobListener listener=new MyJobListener();MyTriggerListener triggerListener=new MyTriggerListener();MySchedulerListener schedulerListener=new MySchedulerListener();//通過調(diào)度器的ListenerManager注冊JobListener和TriggerListener//scheduler.getListenerManager().addJobListener(listener,and(jobGroupEquals("group2"),keyEquals(jobKey("printerJob","group2"))));scheduler.getListenerManager().addJobListener(listener,keyEquals(jobKey("printerJob","group2")));scheduler.getListenerManager().addTriggerListener(triggerListener,keyEquals(triggerKey("jobListenerTrigger","group2")));scheduler.getListenerManager().addSchedulerListener(schedulerListener); //刪除JobListener //scheduler.getListenerManager().removeJobListener(listener.getName()); //刪除TriggerListener //scheduler.getListenerManager().removeTriggerListener(triggerListener.getName()); //刪除SchedulerListener //scheduler.getListenerManager().removeSchedulerListener(schedulerListener);scheduler.start();scheduler.scheduleJob(jobDetail,trigger);}
  • ?

四、Quartz的持久化配置

??Quartz提供兩種持久化方式,基于內(nèi)存的RAMJobStore方式和基于磁盤介質(zhì)的JDBCJobStore方式。上文實(shí)例使用的是Quartz的基于內(nèi)存的持久化方式,優(yōu)點(diǎn)是內(nèi)存存儲執(zhí)行高效,缺點(diǎn)很明顯,當(dāng)操作系統(tǒng)崩潰或其他異常導(dǎo)致定時器終止將無法恢復(fù)之前狀態(tài)。?
下面介紹Quartz的JDBCJobStore持久化配置,Quartz提供基于多種數(shù)據(jù)庫的持久化配置形式。本文以mySql 5.6為例對Quartz進(jìn)行配置。?
官網(wǎng)下載Quartz的壓縮包。?
首先建立數(shù)據(jù)存儲表,Quartz壓縮包下的\docs\dbTables提供對多種數(shù)據(jù)庫的sql建表語句支持。使用tables_mysql_innodb.sql在mysql數(shù)據(jù)庫中建立相關(guān)數(shù)據(jù)表。注意Quartz默認(rèn)數(shù)據(jù)表以QRTZ_開頭,可以修改為自己的命名規(guī)則。?
一共建立11張表,根據(jù)名稱可猜測大致?
QRTZ_FIRED_TRIGGERS;?
QRTZ_PAUSED_TRIGGER_GRPS;?
QRTZ_SCHEDULER_STATE;?
QRTZ_LOCKS;?
QRTZ_SIMPLE_TRIGGERS;?
QRTZ_SIMPROP_TRIGGERS;?
QRTZ_CRON_TRIGGERS;?
QRTZ_BLOB_TRIGGERS;?
QRTZ_TRIGGERS;?
QRTZ_JOB_DETAILS;?
QRTZ_CALENDARS;

??在項(xiàng)目中進(jìn)行配置,Quartz使用JDBC進(jìn)行數(shù)據(jù)庫連接。導(dǎo)入最新的mysql jdbc connector數(shù)據(jù)源。因?yàn)槭褂玫氖禽^新的5.6版本mysql,建議使用最新的msql myconnector,不然有可能會報sql格式錯誤異常。

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.31</version> </dependency>
  • ?

resources目錄下建立quartz.properties進(jìn)行配置,Quartz會自動加載。關(guān)鍵配置參數(shù)和相關(guān)解釋如下:

#集群配置 org.quartz.scheduler.instanceName: DefaultQuartzScheduler #如果運(yùn)行在非集群環(huán)境中,自動產(chǎn)生值將會是 NON_CLUSTERED。假如是在集群環(huán)境下,將會是主機(jī)名加上當(dāng)前的日期和時間。 org.quartz.scheduler.instanceId:AUTO org.quartz.scheduler.rmi.export: false org.quartz.scheduler.rmi.proxy: false org.quartz.scheduler.wrapJobExecutionInUserTransaction: false #Quartz 自帶的線程池實(shí)現(xiàn)類是 org.quartz.smpl.SimpleThreadPool org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool #根據(jù)任務(wù)的多少靈活配置線程池中線程的數(shù)量 org.quartz.threadPool.threadCount: 10 org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true org.quartz.jobStore.misfireThreshold: 60000 #============================================================================ # Configure JobStore #============================================================================#默認(rèn)配置,數(shù)據(jù)保存到內(nèi)存 #org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore #持久化配置 org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.useProperties:true #數(shù)據(jù)庫表前綴 #org.quartz.jobStore.tablePrefix:qrtz_ #注意這里設(shè)定的數(shù)據(jù)源名稱為dbqz org.quartz.jobStore.dataSource:dbqz#============================================================================ # Configure Datasources #============================================================================ #org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE #org.quartz.dataSource.dbqz.validationQuery=SELECT 1 #JDBC驅(qū)動 org.quartz.dataSource.dbqz.driver:com.mysql.jdbc.Driver org.quartz.dataSource.dbqz.URL:jdbc:mysql://127.0.0.1:3306/quartz?useUnicode=true&characterEncoding=UTF-8 org.quartz.dataSource.dbqz.user:數(shù)據(jù)庫用戶名 org.quartz.dataSource.dbqz.password:密碼 org.quartz.dataSource.dbqz.maxConnection:10
  • ?

實(shí)例代碼:

public class DBScheduleTest {private static String JOB_GROUP_NAME = "ddlib";private static String TRIGGER_GROUP_NAME = "ddlibTrigger";public static void main(String[] args) throws SchedulerException, ParseException { // startJob();resumeJob();}public static void startJob() throws SchedulerException {SchedulerFactory factory = new StdSchedulerFactory();Scheduler scheduler=factory.getScheduler();JobDetail jobDetail=newJob(PersistenceJob.class).withIdentity("job_1","jobGroup1").build();Trigger trigger=newTrigger().withIdentity("trigger_1","triggerGroup1").startNow().withSchedule(simpleSchedule().repeatSecondlyForTotalCount(100)).build();scheduler.scheduleJob(jobDetail,trigger);scheduler.start();try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}scheduler.shutdown();}public static void resumeJob() throws SchedulerException {SchedulerFactory factory = new StdSchedulerFactory();Scheduler scheduler = factory.getScheduler();// 獲取調(diào)度器中所有的觸發(fā)器組List<String> triggerGroups = scheduler.getTriggerGroupNames();// 重新恢復(fù)在triggerGroup1組中,名為trigger_1觸發(fā)器的運(yùn)行for (int i = 0; i < triggerGroups.size(); i++) {List<String> triggers = scheduler.getTriggerGroupNames();for (int j = 0; j < triggers.size(); j++) {Trigger tg = scheduler.getTrigger(new TriggerKey(triggers.get(j), triggerGroups.get(i)));// 根據(jù)名稱判斷if (tg instanceof SimpleTrigger&& tg.getDescription().equals("triggerGroup1.trigger_1")) {// 恢復(fù)運(yùn)行scheduler.resumeJob(new JobKey(triggers.get(j),triggerGroups.get(i)));}}}scheduler.start();} }
  • ?

自定義Job類PersistenceJob:

public class PersistenceJob implements Job {private static int i=0;@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("job執(zhí)行--"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"--"+i++);} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

startJob()執(zhí)行一個job,并設(shè)置觸發(fā)器,每隔一秒執(zhí)行一次,一共執(zhí)行100次,在10秒之后,線程終止并讓schedule關(guān)閉。觀察數(shù)據(jù)庫表結(jié)構(gòu)。該job以及job的執(zhí)行情況已經(jīng)更新進(jìn)數(shù)據(jù)表。?
resumeJob()重新創(chuàng)建schedule,并從數(shù)據(jù)庫中查找擁有相同key的觸發(fā)器,schedule.resuemeJob()恢復(fù)任務(wù)的運(yùn)行。當(dāng)任務(wù)結(jié)束刪除數(shù)據(jù)表中的Job相關(guān)注冊信息。

五、Spring集成Quartz

??spring提供對quartz的集成。通過對quartz相關(guān)bean的配置實(shí)現(xiàn)對quartz的加載。以spring boot為例,首先在maven項(xiàng)目的pom.xml中導(dǎo)入相關(guān)包:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
  • ?

??然后同上文配置quartz的jdbc持久化存儲。?
??在resources下添加quartz-context.xml,對quartz進(jìn)行配置。?
其中對job的構(gòu)建方式有兩種,一種是通過org.springframework.scheduling.quartz.JobDetailFactoryBean進(jìn)行job構(gòu)建,要實(shí)現(xiàn)Job接口。另一種是通過org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean對job進(jìn)行構(gòu)建,不用實(shí)現(xiàn)job接口。?
??quartz-context.xml配置如下:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"><!--job任務(wù)配置,有兩種方式--><!--方式一:使用JobDetailFactoryBean,要求關(guān)聯(lián)的類要實(shí)現(xiàn)Job接口--><bean id="jobDetailTester" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"><property name="durability" value="true"></property><property name="requestsRecovery" value="true"></property><property name="jobClass" value="com.czx.job.HelloJob"></property><property name="jobDataAsMap"><map><entry key="size" value="10"></entry></map></property></bean><!--方式二:使用MethodInvokingJobDetailFactoryBean--><!--注意,MethodInvokingJobDetailFactoryBean的提示:NOTE: JobDetails created via this FactoryBean are notserializable and thus not suitable for persistent job stores.You need to implement your own Quartz Job as a thin wrapper for each casewhere you want a persistent job to delegate to a specific service method.因?yàn)槭褂玫幕跀?shù)據(jù)庫的持久化存儲,所以在使用這種方式構(gòu)建job對象時會報java序列化異常:Java.io.NotSerializableException:Unable to serialize JobDataMap for insertion into database becausethe value of property 'methodInvoker' is not serializable:org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean--><!--此種方式不推薦--><bean id="methodInvokingJobDetailTester" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="concurrent" value="false"></property><property name="targetObject"><ref bean="springJobTester"></ref><!--要關(guān)聯(lián)的job任務(wù)類--></property><property name="targetMethod"><value>service</value></property><!--要執(zhí)行方法的名稱--></bean><bean id="springJobTester" class="com.czx.job.SpringJobTester"></bean><!--quartz 2.x scheduler啟動開始--><bean name="scheduleFactory" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="autoStartup" value="true"></property><property name="startupDelay" value="10"></property><property name="triggers"><list><ref bean="cronTriggerTester"></ref><!--<ref bean="simpleTriggerTester"></ref> 會報序列化異常,原因如上所述--></list></property><property name="applicationContextSchedulerContextKey" value="applicationContext"></property><property name="configLocation" value="classpath:quartz.properties"></property></bean><!--觸發(fā)器Trigger配置--><!--基于CronTrigger的觸發(fā)方式--><bean id="cronTriggerTester" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="jobDetail" ref="jobDetailTester"></property><property name="cronExpression" value="0/5 * * ? * MON"></property></bean><!--基于SimpleTrigger的觸發(fā)方式--><bean id="simpleTriggerTester" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"><property name="jobDetail" ref="methodInvokingJobDetailTester"></property><property name="repeatInterval" value="2000"></property><property name="startDelay" value="0"></property><property name="jobDataAsMap"><map><entry key="size" value="10"></entry></map></property><property name="repeatCount" value="10"></property></bean> </beans>
  • ?

六、基于Spring QuartzJobBean的Quartz Job配置方式

??在實(shí)際情況中,自定義的job往往需要調(diào)用service和dao層的方法,對相關(guān)操作進(jìn)行持久化。為了避免各模塊間的高耦合。引入Spring QuartzJobBean,然后通過反射機(jī)制對具體業(yè)務(wù)邏輯方法進(jìn)行調(diào)用。Spring QuartzJobBean是一個實(shí)現(xiàn)Job接口的抽象類,閱讀源碼發(fā)現(xiàn)executeInternal()在重寫excute()的同時,將JobDetail中定義的DataMap鍵值映射為繼承其子類的成員變量。我們通過繼承QuartzJobBean定義自己的JobBean,然后設(shè)置與xml中對應(yīng)job dataMap鍵值對相同的配置項(xiàng)為成員變量。通過設(shè)置jobData的targetClass和targetMethod兩個鍵值對,來傳遞需要調(diào)用的業(yè)務(wù)類中的具體方法信息,最后在自定義的JobBean中通過反射機(jī)制獲取該方法。具體實(shí)例如下:?
??首先定義繼承QuartzJobBean的JobBean,MyQuartzJobBean.java

public class MyQuartzJobBean extends QuartzJobBean{/**目標(biāo)類*/private String targetObject;/**要執(zhí)行的方法*/private String targetMethod;@Overrideprotected void executeInternal(JobExecutionContext context)//executeInternal方法會將配置的job Data 鍵-值 作為該類的成員變量throws JobExecutionException {try {ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");Object targetClass=ctx.getBean(targetObject);Method method=null;//反射機(jī)制調(diào)用method=targetClass.getClass().getMethod(targetMethod,new Class[]{JobExecutionContext.class});method.invoke(targetClass,new Object[]{context});} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}catch (Exception e){e.printStackTrace();}}//不可刪除,QuartzJobBean通過set的方法,將job data值賦值給成員變量public void setTargetObject(String targetObject) {this.targetObject = targetObject;}public void setTargetMethod(String targetMethod) {this.targetMethod = targetMethod;} }
  • ?

??定義具體業(yè)務(wù)類SpringJobTester.java,實(shí)現(xiàn)具體Job的業(yè)務(wù)邏輯。

public class SpringJobTester{//實(shí)現(xiàn)Job的具體業(yè)務(wù)方法public void someService(JobExecutionContext context){SimpleDateFormat df=new SimpleDateFormat("HH:mm:ss");System.out.println("Hello SpringJobTester!----"+df.format(new Date()));} }
  • ?

??quartz-context.xml配置如下:

<bean id="proxyJobBeanTester" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"><property name="durability" value="true"></property><property name="requestsRecovery" value="true"></property><property name="jobClass" value="com.czx.job.MyQuartzJobBean"></property><property name="jobDataAsMap"> <!--使用JobData進(jìn)行傳參指定具體job類和具體的執(zhí)行方法,與MyQuartzJobBean成員變量對應(yīng)--><map><entry key="targetObject" value="springJobTester"></entry><!--具體業(yè)務(wù)類的引用--><entry key="targetMethod" value="someService"></entry><!--具體業(yè)務(wù)方法名--></map></property></bean><bean id="myQuartzJobBean" class="com.czx.job.MyQuartzJobBean"></bean><!--通過spring applicationContext獲得該bean--><bean id="springJobTester" class="com.czx.job.SpringJobTester"></bean><!--scheduler配置啟動--><bean name="scheduleFactory" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="autoStartup" value="true"></property><property name="startupDelay" value="5"></property><property name="triggers"><list><ref bean="simpleTriggerForProxy"/></list></property><property name="applicationContextSchedulerContextKey" value="applicationContext"></property><property name="configLocation" value="classpath:quartz.properties"></property></bean><!--觸發(fā)器Trigger配置--> <!--基于SimpleTrigger的觸發(fā)方式--><bean id="simpleTriggerForProxy" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"><property name="jobDetail" ref="proxyJobBeanTester"></property><property name="repeatInterval" value="2000"></property> <!--觸發(fā)間隔2秒--><property name="startDelay" value="1"></property><property name="repeatCount" value="10"></property></bean>

轉(zhuǎn)載于:https://my.oschina.net/monroe/blog/1604596

總結(jié)

以上是生活随笔為你收集整理的调度器Quartz的简述与使用总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。