三. 传递数据
在主程序中通过建造模式生成 JobDetail 和 Trigger时,可以传递一些数据, 这样在 Job接口里面通过 JobExecutionContext 上下文对象就可以获取该数据, 从而根据这些数据,来执行不同的操作。
JobDetailBuilder 和 TriggerBuilder 通过调用 usingJobData() 方法,来传递数据。
三.一 通过 Map中的 key 传递数据
三.一.一 接口任务
//获取前台传递过来的数据 public class MyJob5 implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString=sdf.format(new Date()); //通过 jobExecutionContext 来获取对象 JobKey jobKey=jobExecutionContext.getJobDetail().getKey(); System.out.println("名称:"+jobKey.getName()); //获取JobDetaMap 数据对象集合 JobDataMap dataMap= jobExecutionContext.getJobDetail().getJobDataMap(); System.out.println("JobDetail消息:"+dataMap.getString("message")); System.out.println("JobDetail数目:"+dataMap.getInt("count")); System.out.println("JobDetail无Key:"+dataMap.getString("jobDetail")); //获取 Trigger 的集合 Trigger trigger=jobExecutionContext.getTrigger(); System.out.println("Trigger名称:"+trigger.getKey().getName()); //获取Trigger 里面的Map数据 JobDataMap triggerMap=jobExecutionContext.getTrigger().getJobDataMap(); System.out.println("Trigger message:"+triggerMap.get("message")); System.out.println("Trigger code:"+triggerMap.getInt("code")); System.out.println("Trigger 无key:"+triggerMap.getString("trigger")); System.out.println("正在备份数据库:"+dateString); } }
三.一.二 主程序
//工作任务中获取信息 public class SchedulerDemo5 { public static void main(String[] args) throws Exception{ //创建 Scheduler 实例 Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler(); //创建Job JobDetail jobDetail= JobBuilder.newJob(MyJob5.class) .withIdentity("job1","group1") .usingJobData("message","两个蝴蝶飞设置JobDetail 消息") .usingJobData("count",207) .build(); //获取相应的信息 //创建 Trigger Trigger trigger= TriggerBuilder.newTrigger() .withIdentity("trigger1","group1") .startNow() .usingJobData("message","两个蝴蝶飞设置Trigger 消息") .usingJobData("code",200) .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(2)) .build(); //关联一下 scheduler.scheduleJob(jobDetail,trigger); //启动 scheduler.start(); } }
三.一.三 控制台打印
可以准确地获得 JobDetail和 Trigger传递过来的数据,即使 key相同,也依然可以获取。
如果获取的key不存在的话, 那么显示的是默认值 null值。
注意,此时获取的是 String 字符串
System.out.println("JobDetail无Key:"+dataMap.getString("jobDetail"));
jobDetail这个 key不存在,获取的是 null
但如果是 int类型不存在的话
System.out.println("JobDetail无Key:"+dataMap.getInt("jobDetail"));
那么这个时候,就会报错了。
java.lang.ClassCastException: Identified object is not an Integer.
其对应底层代码是:
public int getInt(String key) { //获取值 Object obj = get(key); try { if(obj instanceof Integer) return ((Integer) obj).intValue(); return Integer.parseInt((String)obj); } catch (Exception e) { //不属于 Integer, 抛出异常 throw new ClassCastException("Identified object is not an Integer."); } }
三.二 Job任务通过 setter 方法获取值
在 Job任务里面,定义属性字段,实现相应的setter方法,就可以获取前台传递过来的数据了。
三.二.一 接口任务
//set方法 获取前台传递过来的数据 public class MyJob6 implements Job { private String message; private int count; private int code; public void setMessage(String message) { this.message = message; } public void setCount(int count) { this.count = count; } public void setCode(int code) { this.code = code; } @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString=sdf.format(new Date()); System.out.println("正在备份数据库:"+dateString); //JobDetail 和Trigger 设置相同的key 的话,取出 trigger 里面的值 System.out.println("输出message:"+message); System.out.println("输出count:"+count); System.out.println("输出code:"+code); } }
三.二.二 主程序获取
//setter方法 工作任务中获取信息 public class SchedulerDemo6 { public static void main(String[] args) throws Exception{ //创建 Scheduler 实例 Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler(); //创建Job JobDetail jobDetail= JobBuilder.newJob(MyJob6.class) .withIdentity("job1","group1") .usingJobData("message","两个蝴蝶飞设置JobDetail 消息") .usingJobData("count",207) .build(); //获取相应的信息 //创建 Trigger Trigger trigger= TriggerBuilder.newTrigger() .withIdentity("trigger1","group1") .startNow() .usingJobData("message","两个蝴蝶飞设置Trigger 消息") .usingJobData("code",200) .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(2)) .build(); //关联一下 scheduler.scheduleJob(jobDetail,trigger); //启动 scheduler.start(); } }
三.二.三 控制台打印输出
通过setter 方法,可以获取前台传递过来的值。
当JobDetail和 Trigger的 key一致时, Job接口中获取到的是 Trigger里面的值,与定义前后顺序无关
四. 有状态和无状态 Job
什么叫做有无状态 Job呢?
简单来说, Job接口里面通过setter方法或者 Map中的key 获取前台传递过来的数据, 能不能把这个数据保存起来呢?
这样,当下一次运行的时候,获取到的值是上一次运行后设置的值,并不是前面通过JobDetail设置过来的值。
如JobDetail 前面传递过来一个 count, 每次执行后 count都加1, 当小于10时,执行什么操作,当>10 &&<20时,执行什么操作,当>20时执行什么操作。 这样的需求也是有的。
从第一部分我们知道, 每一次执行程序,都会重新实例化对象, 每次都是一个新的对象,自然每次都会将属性重新设置,
这个count 数据是不会保存下来的, 是无状态的。
然而,Quartz提供了一个注解 @PersistJobDataAfterExecution, 通过在 Job任务上添加这个注解,
就可以使这个 Job变成有状态的 Job,可以保存这个数据 count。
四.一 演示没有注解,无状态的Job
四.一.一 Job任务
此时,没有注解。
//有无状态Job 设置 public class MyJob7 implements Job { private int count; public void setCount(int count) { this.count = count; } public MyJob7(){ System.out.println("构建对象"); } @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString=sdf.format(new Date()); //让数目自增1 ++ count; System.out.println("count:"+count); System.out.println("当前对象的地址:"+this.toString()); jobExecutionContext.getJobDetail().getJobDataMap().put("count",count); System.out.println("正在备份数据库:"+dateString); } }
四.一.二 主程序
//有无状态job设置 public class SchedulerDemo7 { public static void main(String[] args) throws Exception{ //创建 Scheduler 实例 Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler(); //创建Job JobDetail jobDetail= JobBuilder.newJob(MyJob7.class) .withIdentity("job1","group1") .usingJobData("count",0) .build(); //获取相应的信息 //创建 Trigger Trigger trigger= TriggerBuilder.newTrigger() .withIdentity("trigger1","group1") .startNow() .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(2)) .build(); //关联一下 scheduler.scheduleJob(jobDetail,trigger); //启动 scheduler.start(); } }
四.一.三 控制台打印输出
发现,每次得到的count 数目都是1,是无状态的。
四.二 演示有注解,有状态的Job
在 MyJob7 类上添加注解 @PersistJobDataAfterExecution
@PersistJobDataAfterExecution //添加注解之后,不会每次都重新实例化JobDataMap //有无状态Job 设置 public class MyJob7 implements Job { }
重新运行程序,控制台打印输出:
虽然每次都会重新实例化 MyJob7对象,但是 count 这个数据是保存了下来, 成了有状态的Job
如果添加了注解 @PersistJobDataAfterExecution,当重复运行任务时,虽然每一次都会重新实例化Job对象,但并不会每次都重新实例化 JobDataMap, 那么 JobDataMap里面的数据就可以保存下来了。
谢谢您的观看!!!