Quartz传递数据和有无状态Job(三)下

简介: Quartz传递数据和有无状态Job(三)下

三. 传递数据


在主程序中通过建造模式生成 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();
    }
}


三.一.三 控制台打印

image.png


可以准确地获得 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();
    }
}


三.二.三 控制台打印输出


image.png

通过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();
    }
}

四.一.三 控制台打印输出

image.png


发现,每次得到的count 数目都是1,是无状态的。


四.二 演示有注解,有状态的Job

在 MyJob7 类上添加注解 @PersistJobDataAfterExecution

@PersistJobDataAfterExecution 
//添加注解之后,不会每次都重新实例化JobDataMap
//有无状态Job 设置 
public class MyJob7 implements Job {
}


重新运行程序,控制台打印输出:

image.png



虽然每次都会重新实例化 MyJob7对象,但是 count 这个数据是保存了下来, 成了有状态的Job


如果添加了注解 @PersistJobDataAfterExecution,当重复运行任务时,虽然每一次都会重新实例化Job对象,但并不会每次都重新实例化 JobDataMap, 那么 JobDataMap里面的数据就可以保存下来了。


谢谢您的观看!!!

相关文章
|
缓存 资源调度 网络架构
使用国内的npm镜像源
使用国内的npm镜像源
3965 1
|
物联网 网络性能优化 API
MQTT常见问题之单个消息发送数据不能超过64k如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
数据可视化 JavaScript 前端开发
基于Echarts构建停车场数据可视化大屏
基于Echarts构建停车场数据可视化大屏
402 0
|
6月前
|
机器学习/深度学习 人工智能 监控
Amodal3R:3D重建领域新突破!这个模型让残破文物完美还原,3D重建结果助力文物修复
Amodal3R是一种创新的条件式3D生成模型,通过掩码加权多头交叉注意力机制和遮挡感知层,能够从部分可见的2D图像中重建完整3D形态,仅用合成数据训练即可实现真实场景的高精度重建。
295 13
Amodal3R:3D重建领域新突破!这个模型让残破文物完美还原,3D重建结果助力文物修复
|
11月前
|
数据库 索引
深入理解数据库索引技术:回表与索引下推详解
【10月更文挑战第23天】 在数据库查询性能优化中,索引的使用是提升查询效率的关键。然而,并非所有的索引都能直接加速查询。本文将深入探讨两个重要的数据库索引技术:回表和索引下推,解释它们的概念、工作原理以及对性能的影响。
397 3
|
存储 Java 调度
技术笔记:quartz(从原理到应用)详解篇(转)
技术笔记:quartz(从原理到应用)详解篇(转)
|
10月前
|
监控 Java 数据处理
Spring Batch 是如何工作的?
Spring Batch 是如何工作的?
447 2
|
物联网 应用服务中间件 Linux
CentOS7.9 Nginx+EMQX集群组建MQTTS平台
通过以上步骤,您已成功搭建了一个基于CentOS 7.9、Nginx和EMQX的MQTTS平台。这个平台既能保证数据传输的安全性,又能利用Nginx的负载均衡能力和EMQX的高性能、高并发处理能力,实现稳定高效的消息服务。在部署和配置过程中,务必注意证书、域名以及EMQX配置的正确性,确保系统安全和稳定运行。此外,定期更新软件和系统,以及监控系统性能,也是保证MQTTS平台长期稳定运行的重要环节。
380 3
|
算法 数据挖掘 计算机视觉
刷力扣必备ImageMagick: 强大的图像处理套件
刷力扣必备ImageMagick: 强大的图像处理套件
刷力扣必备ImageMagick: 强大的图像处理套件
|
NoSQL Java Redis
Redis 从入门到精通之Redis操作测试指定key是否存在
在Redis中,可以使用`EXISTS`命令来测试指定的key是否存在。 `EXISTS`命令的基本语法如下: ``` EXISTS key ``` 其中,`key`是要测试的key的名称。如果指定的key存在,命令返回1;如果指定的key不存在,命令返回0。jedis.exists("foo");RedisTemplate的操作,包括测试指定key是否存在。使用该类可以方便地进行Redis操作,而无需关注底层细节。`exists`方法使用`hasKey`方法测试指定key是否存在,如果存在,则返回true;如果不存在,则返回false。
1654 103