正如第一篇文章看到的那樣,實現一個Job是很是簡單的,只須要完成execute()方法就好了。
那麼Jobs與JobDetails有什麼關係呢?簡而言之,Job是對任務的一個具體實現;誰執行了這個任務呢?這就須要JobDetail來實現,因此JobDetail就是Job的一個具體實例;如9點上語文課是一個具體任務,而劉老師在9點上語文課就是這個任務的一個具體實例。
Scheduler執行Job時,在調用execute()方法前會先實例化Job;一旦執行結束,該實例就會被丟棄,而後被垃圾回收。
須要注意的是Job必須有一個無參的構造器;另外在Job類中定義數據屬性是沒有意義的,由於這些屬性值並不會在執行期間保存。java
上面說到Job中沒法定義屬性來傳遞數據,那麼若是咱們須要傳遞數據該怎麼作?就是使用JobDataMap,它是JobDetail的一個屬性。JobDataMap是Map接口的一個實現,而且它有一些便利的方法來儲存和檢索基本類型數據。
修改以前的測試類以下:併發
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class) .withIdentity("helloJob", "group1") .usingJobData("name", "孫悟空") .build();
添加一個值爲孫悟空的name屬性。而後在HelloJob中,咱們就能夠獲取到該屬性:ide
@Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); String name = jobDataMap.getString("name"); System.out.println("hello "+name+", "+ DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")); }
而後運行測試類: 測試
若是在Job類中定義與JobDataMap中鍵值一致的set和get方法,那麼Quartz會自動將這些屬性注入。如:ui
public class HelloJob implements Job{ private String name; @Override public void execute(JobExecutionContext context) throws JobExecutionException { //JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); //String name = jobDataMap.getString("name"); System.out.println("hello "+name+", "+ DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
另外Trigger中也能夠設置JobDataMap屬性,這是爲了在多個Trigger中使用相同的Job。JobExecutionContext 將會合並JobDetail與Trigger的JobDataMap,若是其中屬性名相同,後者將覆蓋前者。可使用JobExecutionContext.getMergedJobDataMap()方法來獲取合併後的JobDataMap。this
@DisallowConcurrentExecution,若是使用該註解,那麼同一時間將只有一個Job實例被執行。如,ReportJob有個實例爲ReportForJoe,那麼同一時間只有一個ReportForJoe被執行。而ReportForMike等均可以執行。
@PersistJobDataAfterExecution,若是使用該註解,在Job被執行結束後,將會更新JobDataMap,這樣下次Job執行後就會使用新的值而不是初始值。
若是使用@PersistJobDataAfterExecution註解,推薦也使用@DisallowConcurrentExecution註解,這是爲了不併發問題致使數據紊亂。spa
execute()方法只容許拋出JobExecutionException異常.net