Quartz-JobDataMap 参数传递
文章目錄
- 概述
- JobDataMap
- Xml 配置方式的值的傳遞
- Quartz官方示例
- Job的狀態與并發
- 其它屬性
- JobExecutionException
- 示例源碼
概述
我們在Quartz-Job 詳解中,講解了純Quartz的參數傳遞,這里我們將通過與Spring結合的方式再次講解一下Quartz中的參數傳遞。
JobDataMap
JobDataMap可用于保存任何數量的(可序列化的)數據對象,我們希望在執行時可以將其提供給作業實例。JobDataMap是Java Map接口的一個實現,并且有一些用于存儲和檢索原始類型的數據的方便方法。
我們來溫習下純Quartz的寫法
// 具體任務 JobDetail JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").usingJobData("jobSays", "Hello World!").usingJobData("myFloatValue", 3.141f).build();HelloJob如下
/*** 具體執行的任務*/ public class HelloJob implements Job {@Overridepublic 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.out.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);} }運行結果
Instance group1.job1 of DumbJob says: Hello World!, and val is: 3.141 Instance group1.job1 of DumbJob says: Hello World!, and val is: 3.141如果在Job類中定義與JobDataMap中鍵值一致的set和get方法,那么Quartz會自動將這些屬性注入。如:
// 具體任務 JobDetail JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").usingJobData("name", "artisan").usingJobData("age", 24).build();HelloJob
import org.quartz.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory;/*** 具體執行的任務*/ public class HelloJob implements Job {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {JobKey key = context.getJobDetail().getKey();System.out.println("Instance " + key + ",姓名:" + name + ",年齡:" + age);} }運行結果
Instance group1.job1,姓名:artisan,年齡:24 Instance group1.job1,姓名:artisan,年齡:24 Instance group1.job1,姓名:artisan,年齡:24另外Trigger中也可以設置JobDataMap屬性,這是為了在多個Trigger中使用相同的Job。
JobExecutionContext 將會合并JobDetail與Trigger的JobDataMap,如果其中屬性名相同,后者將覆蓋前者。
可以使用JobExecutionContext.getMergedJobDataMap()方法來獲取合并后的JobDataMap。
Xml 配置方式的值的傳遞
在spring中,如果HelloJob的方法有參數,那么需要指定一些設定才可以,否則會在運行時有NoSuchMethodException異常發生。
簡單示例
public class HelloJob {public void execute(String args){System.out.println("------ " + args + "------ ");} }xml配置
<!-- 配置JobDetail --> <bean id="springQtzJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><!-- 執行目標job --><property name="targetObject" ref="helloJob"></property><!-- 要執行的方法 --><property name="targetMethod" value="execute"></property><!-- 設置參數--><property name="arguments" value="artisan"></property> </bean>增加一個arguments的變量,設置一個value即可,如果你點進去觀察源代碼,會發現,它其實是一個 Object[] 類型的參數
執行結果
------ artisan------ ------ artisan------如果你想傳遞2個參數,示例如下
public void execute(String name, int age) {System.out.println("------ " + name + ":" + age + "------ "); } <!-- 設置參數--> <property name="arguments"><list><value>artisan</value><value>23</value></list> </property>當然,我們也可以傳遞Map,Set,JavaBean對象等等,這里只是拋磚引玉。
Quartz官方示例
第4個案例
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/examples/Example4.html
示例演示了靜態變量和非靜態變量的修改,只有靜態成員才能改變
package com.xgj.quartz.quartzItself.jobDataMapOfficalDemo;import java.text.SimpleDateFormat; import java.util.Date;import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.quartz.PersistJobDataAfterExecution;@PersistJobDataAfterExecution @DisallowConcurrentExecution public class ColorJob implements Job {public static final String FAVORITE_COLOR = "favorite color";public static final String EXECUTION_COUNT = "count";// 由于Quartz會在每次執行時重新實例化一個類,因此成員非靜態成員變量不能用于維護狀態!private int _counter = 1;public void execute(JobExecutionContext context)throws JobExecutionException {JobKey jobKey = context.getJobDetail().getKey();JobDataMap data = context.getJobDetail().getJobDataMap();String favoriteColor = data.getString(FAVORITE_COLOR);int count = data.getInt(EXECUTION_COUNT);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");System.out.println("任務Key: " + jobKey + " ,執行時間: "+ sdf.format(new Date()) + "\n" + " 傳遞參數(favorite color): "+ favoriteColor + "\n" + " 傳遞參數(count): " + count + "\n"+ " ColorJob非靜態變量值: " + _counter + "\n");count++;data.put(EXECUTION_COUNT, count);data.put(FAVORITE_COLOR, "黃色");_counter++;}} package com.xgj.quartz.quartzItself.jobDataMapOfficalDemo;import static org.quartz.DateBuilder.nextGivenSecondDate; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger;import java.text.SimpleDateFormat; import java.util.Date;import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.SchedulerMetaData; import org.quartz.SimpleTrigger; import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class JobStateExample {public void run() throws Exception {Logger log = LoggerFactory.getLogger(JobStateExample.class);SchedulerFactory sf = new StdSchedulerFactory();Scheduler sched = sf.getScheduler();// 在當前時間10秒后運行Date startTime = nextGivenSecondDate(null, 10);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// 通過過JobDetail封裝ColorJob,同時指定Job在Scheduler中所屬組及名稱,這里,組名為group1,而名稱為job1。JobDetail job1 = newJob(ColorJob.class).withIdentity("job1", "group1").build();// 創建一個SimpleTrigger實例,指定該Trigger在Scheduler中所屬組及名稱。// 接著設置調度的時間規則.當前時間10秒后運行,每10秒運行一次,共運行4次SimpleTrigger trigger1 = newTrigger().withIdentity("trigger1", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(4)).build();// 將參數傳遞入任務的數據Map中job1.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "綠色");job1.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);// 注冊并進行調度Date scheduleTime1 = sched.scheduleJob(job1, trigger1);log.error("任務key: " + job1.getKey() + ",執行運行時間: "+ sdf.format(scheduleTime1) + ",觸發器重復執行次數: "+ trigger1.getRepeatCount() + ",觸發器執行時間: "+ trigger1.getRepeatInterval() / 1000 + "秒");// 第二個任務JobDetail job2 = newJob(ColorJob.class).withIdentity("job2", "group1").build();SimpleTrigger trigger2 = newTrigger().withIdentity("trigger2", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(4)).build();// 傳遞數據job2.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "紅色");job2.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);Date scheduleTime2 = sched.scheduleJob(job2, trigger2);log.error("第二個任務key: " + job2.getKey().toString() + ",執行運行時間: "+ sdf.format(scheduleTime2) + ",觸發器重復執行次數: "+ trigger2.getRepeatCount() + ",觸發器執行時間: "+ trigger2.getRepeatInterval() / 1000 + "秒");// 調度器啟動sched.start();try {Thread.sleep(60L * 1000L);} catch (Exception e) {}// 調度器停止sched.shutdown(true);SchedulerMetaData metaData = sched.getMetaData();log.error("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");}public static void main(String[] args) throws Exception {JobStateExample example = new JobStateExample();example.run();}}執行結果如下
INFO StdSchedulerFactory - Using default implementation for ThreadExecutor INFO SimpleThreadPool - Job execution threads will use class loader of thread: main INFO SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl INFO QuartzScheduler - Quartz Scheduler v.2.2.3 created. INFO RAMJobStore - RAMJobStore initialized. INFO QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.NOT STARTED.Currently in standby mode.Number of jobs executed: 0Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.INFO StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' INFO StdSchedulerFactory - Quartz scheduler version: 2.2.3 ERROR JobStateExample - 任務key: group1.job1,執行運行時間: 2017-11-13 10:29:40,觸發器重復執行次數: 4,觸發器執行時間: 10秒 ERROR JobStateExample - 第二個任務key: group1.job2,執行運行時間: 2017-11-13 10:29:40,觸發器重復執行次數: 4,觸發器執行時間: 10秒 INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. 任務Key: group1.job2 ,執行時間: 2017-11-13 10:29:40傳遞參數(favorite color): 紅色傳遞參數(count): 1ColorJob非靜態變量值: 1任務Key: group1.job1 ,執行時間: 2017-11-13 10:29:40傳遞參數(favorite color): 綠色傳遞參數(count): 1ColorJob非靜態變量值: 1任務Key: group1.job1 ,執行時間: 2017-11-13 10:29:50傳遞參數(favorite color): 黃色傳遞參數(count): 2ColorJob非靜態變量值: 1任務Key: group1.job2 ,執行時間: 2017-11-13 10:29:50傳遞參數(favorite color): 黃色傳遞參數(count): 2ColorJob非靜態變量值: 1任務Key: group1.job1 ,執行時間: 2017-11-13 10:30:00傳遞參數(favorite color): 黃色傳遞參數(count): 3ColorJob非靜態變量值: 1任務Key: group1.job2 ,執行時間: 2017-11-13 10:30:00傳遞參數(favorite color): 黃色傳遞參數(count): 3ColorJob非靜態變量值: 1任務Key: group1.job1 ,執行時間: 2017-11-13 10:30:10傳遞參數(favorite color): 黃色傳遞參數(count): 4ColorJob非靜態變量值: 1任務Key: group1.job2 ,執行時間: 2017-11-13 10:30:10傳遞參數(favorite color): 黃色傳遞參數(count): 4ColorJob非靜態變量值: 1任務Key: group1.job1 ,執行時間: 2017-11-13 10:30:20傳遞參數(favorite color): 黃色傳遞參數(count): 5ColorJob非靜態變量值: 1任務Key: group1.job2 ,執行時間: 2017-11-13 10:30:20傳遞參數(favorite color): 黃色傳遞參數(count): 5ColorJob非靜態變量值: 1INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete. ERROR JobStateExample - Executed 10 jobs.Job的狀態與并發
@DisallowConcurrentExecution:同一時間將只有一個Job實例被執行。
@PersistJobDataAfterExecution:在Job被執行結束后,將會更新JobDataMap,這樣下次Job執行后就會使用新的值而不是初始值。 上面的示例中,如果不用此注解,成員變量的值下次調用也不會有改變。
如果使用@PersistJobDataAfterExecution注解,推薦也使用@DisallowConcurrentExecution注解,這是為了避免并發問題導致數據紊亂。
其它屬性
Durability,持久性;如果Job是非持久性的,一旦沒有Trigger與其相關聯,它就會從Scheduler中被刪除。也就是說Job的生命周期和其Trigger是關聯的。
RequestsRecovery,如果為true,那么在Scheduler異常中止或者系統異常關閉后,當Scheduler重啟后,Job會被重新執行。
JobExecutionException
execute()方法只允許拋出JobExecutionException異常
示例源碼
代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster
總結
以上是生活随笔為你收集整理的Quartz-JobDataMap 参数传递的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Quartz-Spring通过 @Sch
- 下一篇: Spring-常见问题25问