Quartz定时任务的组件API[通俗易懂]

title:Quartz技术(二)-Quartz组件APIcategories:后端tags:定时任务本讲主要说明Quartz中重要的几个组件的API。Scheduler(调度器)Scheduler的生命期,从SchedulerFactory创建它时开始,到Scheduler调用shutdown()方法时结束;Scheduler被创建后,可以增加、删除和列举Job和Tri…

大家好,又见面了,我是你们的朋友全栈君。

个人博客:https://domyselfzy.coding.me/

本讲主要说明Quartz中重要的几个组件的API。

Scheduler(调度器)

Scheduler的生命期,从SchedulerFactory创建它时开始,到Scheduler调用shutdown()方法时结束;Scheduler被创建后,可以增加、删除和列举Job和Trigger,以及执行其它与调度相关的操作(如暂停Trigger)。但是,Scheduler只有在调用start()方法后,才会真正地触发trigger(即执行job)。

上面说了,Scheduler是由Factory创建的,有两种方式来创建一个Scheduler。

  1. 直接获取
// 1. 创建 SchedulerFactory
SchedulerFactory factory = new StdSchedulerFactory();
// 2. 从工厂中获取调度器实例
Scheduler scheduler = factory.getScheduler();
  1. 自己配置FactoryBean
/** * <p>初始化一个构建Scheduler的工厂</p> */
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws Exception { 
   
    SchedulerFactoryBean factory = new SchedulerFactoryBean();
    factory.setQuartzProperties(quartzProperties());
    factory.setOverwriteExistingJobs(true);
    factory.afterPropertiesSet();
    return factory;
}

/** * 通过SchedulerFactoryBean获取Scheduler的实例 */
@Bean
public Scheduler scheduler() throws Exception { 
   
    Scheduler scheduler = schedulerFactoryBean().getScheduler();
    if (scheduler.isStarted()) { 
   
        scheduler.shutdown();
    }

		scheduler.start();
    return scheduler;
}

第二种方式,有一个好处,可以初始化指定的配置文件,也不一定必须放在ClassPath的指定位置。

Job

一个job就是一个实现了Job接口的类,该接口只有一个方法:

public interface Job { 
   

public void execute(JobExecutionContext context)
  throws JobExecutionException;
}

简单来说,Job的使命就是你将需要执行的任务逻辑,写在execute()方法中。
当一个定时任务被执行时,execute()方法由调度程序的一个线程调用。
我们可以在Job中定义自己当前作业需要执行的逻辑,如:

@Override
@SuppressWarnings("unchecked")
@Transactional(rollbackFor = Exception.class)
public void execute(JobExecutionContext jobExecutionContext) { 
   
    JobDetail jobDetail = jobExecutionContext.getJobDetail();
    JobDataMap jobDataMap = jobDetail.getJobDataMap();
   
    messageTemplate = (RedisTemplate<String, String>) jobDataMap.get("messageTemplate");
    scheduler = (Scheduler) jobDataMap.get("scheduler");

    //处理分布式的锁问题
    String lockName = QuartzConstants.LOCK_KEY + QuartzConstants.JMS_JOIN_SIGN + task.getId();
    Boolean absent = messageTemplate.opsForValue().setIfAbsent(lockName, "task-job-lock");
    try { 
   
        if (BooleanUtils.isNotTrue(absent)) { 
   
            logger.info("Get lock fail, current job is executing , please wait next invoke , task {}"
                    , task.toString());
            return;
        }

        //避免程序服务挂掉,导致锁无法释放,设定20s,避免定时任务相距时间太短,如果有问题,再调整
        messageTemplate.expire(lockName, 20, TimeUnit.SECONDS);
    } catch (Exception e) { 
   
        e.printStackTrace();
        logger.error("send message error, task: {}", task.toString());
    } finally { 
   
        if (BooleanUtils.isTrue(absent)) { 
   
            logger.info("Free lock");
            messageTemplate.delete(lockName);
        }
    }
}

上面代码,就定义了一个我自己的逻辑,处理多机集群时,同步触发的任务锁。

JobExecutionContext

这个对象实例,将包含作业执行过程的上下文信息,可以在执行当前任务过程中获取相应信息。同时,你也可以在创建一个定时任务时将自己需要的信息放入到该上下文中。
**注意:**JobExecutionContext对象中保存着该job运行时的一些信息 ,执行job的scheduler的引用,触发job的trigger的引用,JobDetail对象引用,以及一些其它信息。

JobDetail(实例化作业)

上面说的Job,其实并不是真正可以执行的作业任务,它只是定义了一个作业能做什么,需要做什么事。真正需要被任务调度的其实的一个实例化Job的JobDetail。你可以有两种理解方式,一种是Job是一个父类,JobDetail是它的实现类(当然实际并不是,这里只是方便理解),二是,JobDetail类似Java中Number这样的包装类,将Job包装了一次,并且封装了更多的信息。

如何实例化一个JobDetail呢?

// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
  .withIdentity("myJob", "group1") // name "myJob", group "group1"
  .build();

很简单,只需要将你需要执行的一个Job,直接丢给JobDetail就可以了。
但是要特别注意就是,你传入个Map中的对象序列号的问题,建议采用Java标准序列化。
除此之外,上文也说了,JobExecutionContext不是还可以包含一些自定义信息吗?,在这里就可以定义了。

JobDataMap

在JobDetail中,可以使用JobDataMap来设置更多你需要带入到Job中的信息。
构建JobDetail时,可以将数据放入Map中

// define the job and tie it to our DumbJob class
JobDetail job = newJob(DumbJob.class)
  .withIdentity("myJob", "group1") // name "myJob", group "group1"
  .usingJobData("jobSays", "Hello World!")
  .usingJobData("myFloatValue", 3.141f)
  .build();

在Job执行过程中,可以从中取出来相应数据。

public class DumbJob implements Job { 
   

    public DumbJob() { 
   
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    { 
   
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getJobDetail().getJobDataMap();

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
  }

好了,看到这里,不知道大家有没有疑惑?为啥好多地方都定义了withIdentity这个语句?

这里说明一下Quartz中Key的作用

Key(Job或者Trigger的唯一表示)

简答来说,不管是Job还是Trigger都要有个名字,Quartz还可以对其进行分组,这两样加起来正好作为了它的唯一标识。

将Job和Trigger注册到Scheduler时,可以为它们设置key,配置其身份属性。Job和Trigger的key(JobKey和TriggerKey)可以用于将Job和Trigger放到不同的分组(group)里,然后基于分组进行操作。同一个分组下的Job或Trigger的名称必须唯一,即一个Job或Trigger的key由名称(name)和分组(group)组成。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/127455.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Swift4 String截取字符串

    Swift4 String截取字符串varstr1="AlexanderYeah";//1截取字符串的第一种方式//prefix截取前3个字符串varstr2=str1.prefix(3);print(str2);//suffix截取后3个字符串varstr3=str1.suffix(3);print(str3);//2截取一个范围的字符串//从0开始到倒数第二位结…

  • 彻底澄清子网掩码、反掩码、通配符掩码以及ospf network命令误区

    彻底澄清子网掩码、反掩码、通配符掩码以及ospf network命令误区1.子网掩码(IPsubnetmask)用途:标识一个IP地址的网络位,主机位网络设备判断目的IP跟自己是否同一网段的依据。特点:1和0绝对不可能间隔,1总在0的前面。网络通信角度,子网掩码只具有本地意义。跟对端没有匹配的硬性要求。误区:一条链路两端的子网掩码必须一致(是习惯不是必须)例外:ospf多路访问网络中,掩码不一致会影响ospf邻居关系建立2.通配符掩码wildcardmask用途:选出一组符合否规则的IP地址特点:0表匹配…

  • h5实现长按复制文本_复制css

    h5实现长按复制文本_复制css复制2333333<style> p{ -webkit-user-select:none; user-select:none; } p>i{ -webkit-user-select:text; user-select:text; } </style> <p>长按复制短码<i>23…

  • 详解List的toArray()方法和toArray(T[] a)方法

    详解List的toArray()方法和toArray(T[] a)方法这两个方法都是将列表List中的元素转导出为数组,不同的是,toArray()方法导出的是Object类型数组,而toArray[T[]a]方法导出的是指定类型的数组。下面是两个方法的申明及说明,摘自Java8的API文档。toArray()方法的分析Object[]toArray()Returnsanarraycontainingalloftheelementsinthislistinpropersequence(fromfirsttolastelem

  • Pytest(6)重复运行用例pytest-repeat[通俗易懂]

    Pytest(6)重复运行用例pytest-repeat[通俗易懂]前言平常在做功能测试的时候,经常会遇到某个模块不稳定,偶然会出现一些bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来。自动化运行用例时候,也会出现偶然的bug,可以针对单个用例,

  • h5页面 请在微信客户端打开链接_如何看到“请在微信客户端打开链接”页面的源码?…

    h5页面 请在微信客户端打开链接_如何看到“请在微信客户端打开链接”页面的源码?…在H5学习的过程中,看一些好的H5是很有必要的。但是经常有一些H5打开以后在页面显示如下,阻碍了我们探索的脚步~这是因为H5的开发者调用了微信获取用户信息的权限,这个时候你在浏览器打开获取不到微信用户的信息,自然会出现这样的页面了。但是,如果你探索的欲望比较强,那么也是可以看到源码的~具体步骤如下:①安装微信web开发者工具②在手机端打开你要查看的页面,复制页面的链接③进入微信web开发者工具,选…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号