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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

quartzjob传递传输_Quartz教程三:Job与JobDetail介绍

發布時間:2023/12/19 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 quartzjob传递传输_Quartz教程三:Job与JobDetail介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本系列教程由quartz-2.2.x官方文檔翻譯、整理而來,希望給同樣對quartz感興趣的朋友一些參考和幫助,有任何不當或錯誤之處,歡迎指正;有興趣研究源碼的同學,可以參考我對quartz-core源碼的注釋(進行中)。

正如在教程二中講到的,Job實現起來很容易,該接口只有一個“execute”方法。本節主要關注:Job的特點、Job接口的execute方法以及JobDetail。

你定義了一個實現Job接口的類,這個類僅僅表明該job需要完成什么類型的任務,除此之外,Quartz還需要知道該Job實例所包含的屬性;這將由JobDetail類來完成。

JobDetail實例是通過JobBuilder類創建的,導入該類下的所有靜態方法,會讓你編碼時有DSL的感覺:

import static org.quartz.JobBuilder.*;

讓我們先看看Job的特征(nature)以及Job實例的生命期。不妨先回頭看看教程一中的代碼片段:

// define the job and tie it to our HelloJob class

JobDetail job = newJob(HelloJob.class)

.withIdentity("myJob", "group1") // name "myJob", group "group1"

.build();

// Trigger the job to run now, and then every 40 seconds

Trigger trigger = newTrigger()

.withIdentity("myTrigger", "group1")

.startNow()

.withSchedule(simpleSchedule()

.withIntervalInSeconds(40)

.repeatForever())

.build();

// Tell quartz to schedule the job using our trigger

sched.scheduleJob(job, trigger);

“HelloJob”類可以如下定義:

public class HelloJob implements Job {

public HelloJob() {

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

System.err.println("Hello! HelloJob is executing.");

}

}

可以看到,我們傳給scheduler一個JobDetail實例,因為我們在創建JobDetail時,將要執行的job的類名傳給了JobDetail,所以scheduler就知道了要執行何種類型的job;每次當scheduler執行job時,在調用其execute(…)方法之前會創建該類的一個新的實例;執行完畢,對該實例的引用就被丟棄了,實例會被垃圾回收;這種執行策略帶來的一個后果是,job必須有一個無參的構造函數(當使用默認的JobFactory時);另一個后果是,在job類中,不應該定義有狀態的數據屬性,因為在job的多次執行中,這些屬性的值不會保留。

那么如何給job實例增加屬性或配置呢?如何在job的多次執行中,跟蹤job的狀態呢?答案就是:JobDataMap,JobDetail對象的一部分。

JobDataMap

JobDataMap中可以包含不限量的(序列化的)數據對象,在job實例執行的時候,可以使用其中的數據;JobDataMap是Java Map接口的一個實現,額外增加了一些便于存取基本類型的數據的方法。

將job加入到scheduler之前,在構建JobDetail時,可以將數據放入JobDataMap,如下示例:

JobDetail job = newJob(DumbJob.class)

.withIdentity("myJob", "group1") // name "myJob", group "group1"

.usingJobData("jobSays", "Hello World!")

.usingJobData("myFloatValue", 3.141f)

.build();

在job的執行過程中,可以從JobDataMap中取出數據,如下示例:

public class DumbJob implements Job {

public DumbJob() {

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

JobKey key = context.getJobDetail().getKey();

JobDataMap dataMap = context.getJobDetail().getJobDataMap();

String jobSays = dataMap.getString("jobSays");

float myFloatValue = dataMap.getFloat("myFloatValue");

System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);

}

}

如果你使用的是持久化的存儲機制(本教程的JobStore部分會講到),在決定JobDataMap中存放什么數據的時候需要小心,因為JobDataMap中存儲的對象都會被序列化,因此很可能會導致類的版本不一致的問題;Java的標準類型都很安全,如果你已經有了一個類的序列化后的實例,某個時候,別人修改了該類的定義,此時你需要確保對類的修改沒有破壞兼容性;更多細節,參考現實中的序列化問題。另外,你也可以配置JDBC-JobStore和JobDataMap,使得map中僅允許存儲基本類型和String類型的數據,這樣可以避免后續的序列化問題。

如果你在job類中,為JobDataMap中存儲的數據的key增加set方法(如在上面示例中,增加setJobSays(String val)方法),那么Quartz的默認JobFactory實現在job被實例化的時候會自動調用這些set方法,這樣你就不需要在execute()方法中顯式地從map中取數據了。

在Job執行時,JobExecutionContext中的JobDataMap為我們提供了很多的便利。它是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的數據,則后者會覆蓋前者的值。

下面的示例,在job執行時,從JobExecutionContext中獲取合并后的JobDataMap:

public class DumbJob implements Job {

public DumbJob() {

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

JobKey key = context.getJobDetail().getKey();

JobDataMap dataMap = context.getMergedJobDataMap(); // Note the difference from the previous example

String jobSays = dataMap.getString("jobSays");

float myFloatValue = dataMap.getFloat("myFloatValue");

ArrayList state = (ArrayList)dataMap.get("myStateData");

state.add(new Date());

System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);

}

}

如果你希望使用JobFactory實現數據的自動“注入”,則示例代碼為:

public class DumbJob implements Job {

String jobSays;

float myFloatValue;

ArrayList state;

public DumbJob() {

}

public void execute(JobExecutionContext context)

throws JobExecutionException

{

JobKey key = context.getJobDetail().getKey();

JobDataMap dataMap = context.getMergedJobDataMap(); // Note the difference from the previous example

state.add(new Date());

System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);

}

public void setJobSays(String jobSays) {

this.jobSays = jobSays;

}

public void setMyFloatValue(float myFloatValue) {

myFloatValue = myFloatValue;

}

public void setState(ArrayList state) {

state = state;

}

}

你也許發現,整體上看代碼更多了,但是execute()方法中的代碼更簡潔了。而且,雖然代碼更多了,但如果你的IDE可以自動生成setter方法,你就不需要寫代碼調用相應的方法從JobDataMap中獲取數據了,所以你實際需要編寫的代碼更少了。當前,如何選擇,由你決定。

Job實例

很多用戶對于Job實例到底由什么構成感到很迷惑。我們在這里解釋一下,并在接下來的小節介紹job狀態和并發。

你可以只創建一個job類,然后創建多個與該job關聯的JobDetail實例,每一個實例都有自己的屬性集和JobDataMap,最后,將所有的實例都加到scheduler中。

比如,你創建了一個實現Job接口的類“SalesReportJob”。該job需要一個參數(通過JobdataMap傳入),表示負責該銷售報告的銷售員的名字。因此,你可以創建該job的多個實例(JobDetail),比如“SalesReportForJoe”、“SalesReportForMike”,將“joe”和“mike”作為JobDataMap的數據傳給對應的job實例。

當一個trigger被觸發時,與之關聯的JobDetail實例會被加載,JobDetail引用的job類通過配置在Scheduler上的JobFactory進行初始化。默認的JobFactory實現,僅僅是調用job類的newInstance()方法,然后嘗試調用JobDataMap中的key的setter方法。你也可以創建自己的JobFactory實現,比如讓你的IOC或DI容器可以創建/初始化job實例。

在Quartz的描述語言中,我們將保存后的JobDetail稱為“job定義”或者“JobDetail實例”,將一個正在執行的job稱為“job實例”或者“job定義的實例”。當我們使用“job”時,一般指代的是job定義,或者JobDetail;當我們提到實現Job接口的類時,通常使用“job類”。

Job狀態與并發

關于job的狀態數據(即JobDataMap)和并發性,還有一些地方需要注意。在job類上可以加入一些注解,這些注解會影響job的狀態和并發性。

@DisallowConcurrentExecution:將該注解加到job類上,告訴Quartz不要并發地執行同一個job定義(這里指特定的job類)的多個實例。請注意這里的用詞。拿前一小節的例子來說,如果“SalesReportJob”類上有該注解,則同一時刻僅允許執行一個“SalesReportForJoe”實例,但可以并發地執行“SalesReportForMike”類的一個實例。所以該限制是針對JobDetail的,而不是job類的。但是我們認為(在設計Quartz的時候)應該將該注解放在job類上,因為job類的改變經常會導致其行為發生變化。

@PersistJobDataAfterExecution:將該注解加在job類上,告訴Quartz在成功執行了job類的execute方法后(沒有發生任何異常),更新JobDetail中JobDataMap的數據,使得該job(即JobDetail)在下一次執行的時候,JobDataMap中是更新后的數據,而不是更新前的舊數據。和 @DisallowConcurrentExecution注解一樣,盡管注解是加在job類上的,但其限制作用是針對job實例的,而不是job類的。由job類來承載注解,是因為job類的內容經常會影響其行為狀態(比如,job類的execute方法需要顯式地“理解”其”狀態“)。

如果你使用了@PersistJobDataAfterExecution注解,我們強烈建議你同時使用@DisallowConcurrentExecution注解,因為當同一個job(JobDetail)的兩個實例被并發執行時,由于競爭,JobDataMap中存儲的數據很可能是不確定的。

Job的其它特性

通過JobDetail對象,可以給job實例配置的其它屬性有:

Durability:如果一個job是非持久的,當沒有活躍的trigger與之關聯的時候,會被自動地從scheduler中刪除。也就是說,非持久的job的生命期是由trigger的存在與否決定的;

RequestsRecovery:如果一個job是可恢復的,并且在其執行的時候,scheduler發生硬關閉(hard shutdown)(比如運行的進程崩潰了,或者關機了),則當scheduler重新啟動的時候,該job會被重新執行。此時,該job的JobExecutionContext.isRecovering() 返回true。

JobExecutionException

最后,是關于Job.execute(..)方法的一些額外細節。execute方法中僅允許拋出一種類型的異常(包括RuntimeExceptions),即JobExecutionException。因此,你應該將execute方法中的所有內容都放到一個”try-catch”塊中。你也應該花點時間看看JobExecutionException的文檔,因為你的job可以使用該異常告訴scheduler,你希望如何來處理發生的異常。

總結

以上是生活随笔為你收集整理的quartzjob传递传输_Quartz教程三:Job与JobDetail介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 中文在线中文资源 | 成人黄色视屏 | 狠狠躁日日躁夜夜躁2022麻豆 | 日本欧美色 | 亚洲国产精品影院 | 阿娇全套94张未删图久久 | 国产又粗又猛又黄又爽视频 | 色翁荡息又大又硬又粗又爽 | 日一区二区三区 | 爱福利视频一区二区 | 中文一区二区在线 | 国产真实夫妇交换视频 | 九九在线观看视频 | 亲女禁h啪啪宫交 | 高清一区二区在线 | 神马影院一区二区 | 国产午夜精品理论片 | 在线视频你懂得 | 亚洲av无码专区在线播放中文 | 久久大综合 | 精品国产乱码久久久久久牛牛 | 欧美精品网址 | 小辣椒福利视频导航 | 91视频导航| 国产一级片一区 | 一区二区三区四区高清视频 | 动漫美女隐私无遮挡 | 国产黄色观看 | av小片| www视频在线观看免费 | 香蕉钻洞视频 | 亚洲福利影院 | 日韩午夜三级 | 国产人妻精品一区二区三区 | japanese强行粗暴 | 嫩草影院一区二区三区 | 国产精品一品二区三区的使用体验 | 午夜中文字幕 | 亚洲国产天堂 | 国产视频四区 | 亚洲欧美少妇 | 国产精品久久久久久免费观看 | 久久天堂av综合合色蜜桃网 | 成人深夜免费视频 | 久久久久久久综合 | 青青草十七色 | 国产午夜精品在线观看 | 日本一级理论片在线大全 | 91男女视频 | 亚洲永久av | aaa黄色片 | 欧美美女黄色 | 爱情岛论坛成人 | 欧美va视频 | 玩日本老头很兴奋xxxx | 国产福利在线视频观看 | 国产精品99久久久久久动医院 | 亚洲性视频网站 | 激情网站在线 | 日韩欧美电影一区二区三区 | 精品欧美久久 | 成人免费看片98 | 伊人黄网| 青草久久网 | 三级福利| 欧美黄色网 | 看黄网站在线 | 日本免费在线一区 | 97福利影院| 欧美丰满老妇性猛交 | 成年人在线观看视频网站 | 老司机一区二区三区 | 亚洲成人久久久久 | 在线视频亚洲 | 中文字幕亚洲日本 | 操大逼网站 | 国产成人午夜 | 国产福利视频 | 日韩久久久久久久久久 | 亚洲熟女少妇一区 | ww黄色 | 国产一区二区电影 | 中文字幕理伦片免费看 | 91人人视频 | 日本黄色片一级 | 精品国产视频一区二区 | 99亚洲视频 | 亚洲aaaaa特级 | 亚洲色图综合网 | 不卡中文字幕在线 | 色播基地| 久久久免费av | 四虎影视8848hh | 污在线观看 | 久久免费精品视频 | 亚洲精品久久 | 日韩一区二区三区在线看 | 国产一级二级三级精品 | 高清视频在线播放 |