我們一直沒有太深入的去完成 一個job 類,因爲這是跟你的實際應用緊密相關聯的,但是在你的job 處理過程中
如果 發生了異常,那麼會怎麼樣處理呢 ? 客官您往下看…………
------------------------------------我是分割線------------------------------------------------
如果客官看過前面的幾篇 爛的掉渣的 文章後,會知道下面會先貼代碼,一個job類,一個調度類。
但這次有點不同的是這次 沒有爛的掉渣,而是爛的更掉渣,-.-
兩個job類:BadJob1.java 和 BadJob2.java
一個調度類: JobExceptionExample.java
BadJob1.java
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class BadJob2 implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// 任務執行的時間
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String jobName = context.getJobDetail().getKey().getName();
System.out.println("---" + jobName + " 在[ " + dateFormat.format(new Date())+ " ] 執行!! ") ;
System.err.println("--- 在 BadJob 2 中發生 錯誤, 將停止運行!! ");
JobExecutionException e2 = new JobExecutionException(new Exception());
// 設置 將自動 去除 這個任務的觸發器,所以這個任務不會再執行
//e2.setUnscheduleAllTriggers(true);
// 拋出異常
throw e2;
}
}
BadJob2.java
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class BadJob2 implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// 任務執行的時間
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String jobName = context.getJobDetail().getKey().getName();
System.out.println("---" + jobName + " 在[ " + dateFormat.format(new Date())+ " ] 執行!! ") ;
System.err.println("--- 在 BadJob 2 中發生 錯誤, 將停止運行!! ");
JobExecutionException e2 = new JobExecutionException(new Exception());
// 設置 將自動 去除 這個任務的觸發器,所以這個任務不會再執行
e2.setUnscheduleAllTriggers(true);
// 拋出異常
throw e2;
}
}
JobExceptionExample.java
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;
/** 演示 Quartz 如何 處理 從job中 拋出的 JobExecutionExceptions */
public class JobExceptionExample {
public static void main(String[] args) throws Exception {
JobExceptionExample example = new JobExceptionExample();
example.run();
}
public void run() throws Exception {
// 任務執行的時間 格式化
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
System.out.println("--------------- 初始化 -------------------");
// 下一個15秒
Date startTime = nextGivenSecondDate(null, 15);
// badJob1 每10s執行一次 , 拋出異常,並立即重新執行
JobDetail job = newJob(BadJob1.class).withIdentity("badJob1", "group1").usingJobData("denominator", "0").build();
SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(10).repeatForever()).build();
Date ft = sched.scheduleJob(job, trigger);
System.out.println(job.getKey().getName() + " 將在: " + dateFormat.format(ft) + " 時運行.並且重複: "
+ trigger.getRepeatCount() + " 次, 每次間隔 " + trigger.getRepeatInterval() / 1000 + " 秒");
// badJob2 每5秒執行一次 , 並且 會拋出異常,然後 不再執行
job = newJob(BadJob2.class).withIdentity("badJob2", "group1").build();
trigger = newTrigger().withIdentity("trigger2", "group1").startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();
ft = sched.scheduleJob(job, trigger); //
System.out.println(job.getKey().getName() + " 將在: " + dateFormat.format(ft) + " 時運行.並且重複: "
+ trigger.getRepeatCount() + " 次, 每次間隔 " + trigger.getRepeatInterval() / 1000 + " 秒");
sched.start();
System.out.println("------- 開始調度 (調用.start()方法) ----------------");
try {
// 睡眠 30s
Thread.sleep(60L * 1000L);
} catch (Exception e) {
}
sched.shutdown(false);
// 顯示一下 已經執行的任務信息
SchedulerMetaData metaData = sched.getMetaData();
System.out.println("~~~~~~~~~~ 執行了 " + metaData.getNumberOfJobsExecuted() + " 個 jobs.");
}
}
說明:
1 類JobExceptionExample.java 沒什麼可說的了,完全 按套路走的
2 類BadJob1 的代碼 34-44 行 從Map 中取出 denominator 如果 是0 拋出異常,然後將denominator設置成1,也就是說只有第一次會有異常拋出,以後都 正常
代碼 41 行是關鍵: e2.setRefireImmediately(true); 它設置了 job 類拋出異常後的處理方式 ,此處意爲 發生異常後 立即重新執行
3 類BadJob2 的代碼 和 BadJob1 不同,它沒有判斷,執行一次 就拋出一次異常,
但在 第26行處: e2.setUnscheduleAllTriggers(true);
設置了 去掉它的 觸發器, 也就意味着 BadJob2 如果 發生異常,就沒有機會再執行了 (悲催的孩子) 0.0
提醒: 別忘了 BadJob類上的
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
這兩句註釋
一個小問題: 如果 發生異常 而沒有設置 異常時的處理策略 那會是什麼樣,自己試試把BadJob2 中的 代碼 註釋掉 看看結果吧