execute(JobExecutionContext)原生 Quartz 缺乏:任務運行狀態查看、歷史記錄、異常告警/重試、任務依賴排程。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Run { }
public class SimpleJob {
@Run
public void doit() { Thread.sleep(20000); }
}
public class JobWrapper implements Job {
private String id;
private BatchDescription desc;
private Object realJob;
private Method runMethod;
public JobWrapper() {
id = System.currentTimeMillis() + "_" + Thread.currentThread().getId();
stateChanged(id, JobStatus.INIT);
JobManager.instance().reg(this);
}
public void execute(JobExecutionContext context) throws JobExecutionException {
desc = (BatchDescription) context.getJobDetail().getJobDataMap().get("JobData");
try {
realJob = Class.forName(desc.getClassName()).newInstance();
runMethod = getRunMethod(); // 掃描 @Run 註解方法
stateChanged(id, JobStatus.RUNNING);
runMethod.invoke(realJob, desc.getParamenter());
stateChanged(id, JobStatus.SUCCESS);
} catch (InvocationTargetException e) {
stateChanged(id, JobStatus.EXCEPTION, e.getTargetException().getMessage());
} catch (Exception e) {
stateChanged(id, JobStatus.EXCEPTION, e.getMessage());
}
}
private Method getRunMethod() { ... } // 反射查找 @Run 方法
private void stateChanged(String id, JobStatus status, String msg) {
JobDao.save(id, desc.getClassName(), status, msg, new Date()); // 持久化狀態
}
}
BatchDescription bd = new BatchDescription("com.demo.SimpleJob", "0 6 * * *", null);
JobDetail job = new JobDetail(bd.getClassName() + ".Job", "group", JobWrapper.class);
job.getJobDataMap().put("JobData", bd);
CronTrigger trigger = new CronTrigger(bd.getClassName() + ".Trigger");
trigger.setCronExpression(new CronExpression(bd.getCron()));
scheduler.scheduleJob(job, trigger);
JobManager 維護 DAG,stateChanged 觸發下游任務。