2018年8月20日 星期一

Hello Quartz (Quartz 2.x 一)

※文檔

官網教學連結
官網設定教學連結

W3Cschool Quartz 官網

好心網友翻譯的連結:
第一課 使用 Quartz
第二課 Quartz API,Jobs 和 Triggers 介紹
第三課 關於更多的 Jobs和 JobDetails
第四課 關於更多的 Triggers
第五課 SimpleTriggers
第六課 CronTriggers
第七課 TriggerListeners & JobListeners
第八課 SchedulerListeners
第九課 JobStores
第十課 Configuration, Resource Usage和SchedulerFactory
第十一課 進階(企業)功能
第十二課 Quartz 其他功能


※Hello Quartz

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
    
public class TestQuartz {
    public static void main(String[] args) {
        JobDetail job = JobBuilder.newJob(MyJob.class)
            .withIdentity("myJob1", "group1")
            .build();
    
        Trigger trigger = TriggerBuilder
            .newTrigger()
            .withIdentity("myTrigger1", "group2")
            .startNow()
            .withSchedule(SimpleScheduleBuilder
                .simpleSchedule()
                .withIntervalInSeconds(3)
                .repeatForever())
            .build();
    
        System.out.println(job.getKey()); // group1.myJob1
        System.out.println(trigger.getKey());// group2.myTrigger1
    
        try {
            SchedulerFactory schedFact = new StdSchedulerFactory();
            Scheduler sched = schedFact.getScheduler();
            System.out.println(trigger.getJobKey()); // null
            sched.scheduleJob(job, trigger);
            System.out.println(trigger.getJobKey()); // 註冊之後才能取得 group1.myJob1
            sched.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

※注意官網有靜態 import,如下:
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
之後的代碼,我也會用這種方式

※假設 SchedulerFactory 和 Scheduler 寫在最上面,然後馬上就 start(),最後在呼叫 JobDetail、
Trigger並註冊 scheduleJob,也是可以運行的


public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("xxxxxxxxxxxxx");
    }
}

※Job 就是時間到後要執行的方法



※JobDataMap

JobDetail job = newJob(MyJob.class)
    .withIdentity("myJob", "group1")
    .usingJobData("aaa", "111")
    .usingJobData("bbb", 222)
    .build();
    
Trigger trigger = newTrigger()
    .withIdentity("myTrigger1", "group2")
    .startNow()
    .withSchedule(simpleSchedule()
    .withIntervalInSeconds(3)
    .repeatForever())
    .build();
    
try {
    SchedulerFactory schedFact = new StdSchedulerFactory();
    Scheduler sched = schedFact.getScheduler();
    sched.scheduleJob(job, trigger);
    sched.start();
} catch (SchedulerException e) {
    e.printStackTrace();
}

※使用 JobDataMap 可以塞值



public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobKey key = context.getJobDetail().getKey();
    
        // JobDataMap dataMap = context.getMergedJobDataMap();
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        String a = dataMap.getString("aaa");
        int b = dataMap.getInt("bbb");
    
        System.out.println("key=" + key); // group1.myJob
        System.out.println("a=" + a); // 111
        System.out.println("b=" + b);// 222
    }
}

※取值時,可以使用 getMergedJobDataMap() 或 getJobDetail().getJobDataMap(),但還是有區別的,看下面的 @PersistJobDataAfterExecution



※@DisallowConcurrentExecution

JobDetail job = newJob(MyJob.class).withIdentity("myJob", "group1").build();
Trigger trigger = newTrigger()
    .withIdentity("myTrigger1", "group2")
    .startNow()
    .withSchedule(simpleSchedule()
        .withIntervalInSeconds(3)
        .repeatForever())
    .build();
    
try {
    SchedulerFactory schedFact = new StdSchedulerFactory();
    Scheduler sched = schedFact.getScheduler();
    sched.scheduleJob(job, trigger);
    sched.start();
} catch (SchedulerException e) {
    e.printStackTrace();
}




@DisallowConcurrentExecution
public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            System.out.println("前=" + new Date());
            Thread.sleep(5000);
            System.out.println("後=" + new Date());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

※我設定每3秒執行一次,但 Job 裡會睡 5 秒,所以我還沒加這個註解前會是如下的結果:
前=Tue Aug 21 14:17:44 SGT 2018
前=Tue Aug 21 14:17:47 SGT 2018
後=Tue Aug 21 14:17:49 SGT 2018
前=Tue Aug 21 14:17:50 SGT 2018
後=Tue Aug 21 14:17:52 SGT 2018
前=Tue Aug 21 14:17:53 SGT 2018
後=Tue Aug 21 14:17:55 SGT 2018
前=Tue Aug 21 14:17:56 SGT 2018
後=Tue Aug 21 14:17:58 SGT 2018
前=Tue Aug 21 14:17:59 SGT 2018
後=Tue Aug 21 14:18:01 SGT 2018
前=Tue Aug 21 14:18:02 SGT 2018
後=Tue Aug 21 14:18:04 SGT 2018

※44~49 才是一組,中間會有下一次的執行,但如果加上這個註解,結果如下:

前=Tue Aug 21 14:19:12 SGT 2018
後=Tue Aug 21 14:19:17 SGT 2018
前=Tue Aug 21 14:19:17 SGT 2018
後=Tue Aug 21 14:19:22 SGT 2018
前=Tue Aug 21 14:19:22 SGT 2018
後=Tue Aug 21 14:19:27 SGT 2018
前=Tue Aug 21 14:19:27 SGT 2018
後=Tue Aug 21 14:19:32 SGT 2018
前=Tue Aug 21 14:19:32 SGT 2018
後=Tue Aug 21 14:19:37 SGT 2018
前=Tue Aug 21 14:19:37 SGT 2018

※此時中間沒有插入下一次的執行,是以執行完為主的



※@PersistJobDataAfterExecution

JobDetail job = newJob(MyJob.class)
    .withIdentity("myJob", "group1")
    .usingJobData("aaa", "111")
    .usingJobData("bbb", 222)
    .build();
    
Trigger trigger = newTrigger()
    .withIdentity("myTrigger1", "group2")
    .startNow()
    .withSchedule(simpleSchedule()
        .withIntervalInSeconds(3)
        .repeatForever())
    .build();
    
try {
    SchedulerFactory schedFact = new StdSchedulerFactory();
    Scheduler sched = schedFact.getScheduler();
    sched.scheduleJob(job, trigger);
    sched.start();
} catch (SchedulerException e) {
    e.printStackTrace();
}




@PersistJobDataAfterExecution
public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // JobDataMap dataMap = context.getMergedJobDataMap(); // 不會更新的
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        System.out.println("a=" + dataMap.getString("aaa")); // 111|333
        System.out.println("b=" + dataMap.getInt("bbb"));// 222|444
    
        dataMap.put("aaa", "333");
        dataMap.put("bbb", 444);
    }
}

※註解的意思是執行後可保存資料,如範例的 333 和 444,有加上這個註解以及使用的是 getJobDetail().getJobDataMap() 才可以,使用 getMergedJobDataMap() 不會

※第一次執行後是 111 和 222,之後就都會是 333 和 444 了

※官網有說明加上這個註解後,要考慮是不是也要加上 @DisallowConcurrentExecution

沒有留言:

張貼留言