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)组成。

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • unit 5 Communicating with other users

    unit 5 Communicating with other users
    unit5Communicatingwithotherusers
     
    在命令下还有一些关于通讯的命令。有些还允许实时的通信,提供功能性的chat,当其他人允许你给他发送邮件。

    Real-TimeCommunica

    2022年4月30日
    36
  • u盘文件夹exe病毒彻底_u盘中病毒文件变成快捷方式怎么办

    u盘文件夹exe病毒彻底_u盘中病毒文件变成快捷方式怎么办笔者在使用U盘时,无意之间发现U盘所有文件的后缀名均变为“.exe”,经过查询相关资料,确认这是一种病毒(文件夹EXE病毒)一、简介:木马名称:Worm.Win32.AutoRun.soq,当把U盘插入到一台电脑后,U盘内生成了以原文件夹名字命名的文件,且扩展名为exe,其原理是把原来的文件隐藏,重新生成同名的exe文件。二、解决方案:百度下载USBCleaner,根据软件提示进行操作即可完…

    2022年10月25日
    0
  • mac安装mysql中设置密码遇到的问题和设置快捷命令打开mysql

    mac安装mysql中设置密码遇到的问题和设置快捷命令打开mysql

    2021年9月12日
    57
  • 升级公告:由社区推动的cBridge 2.0功能迭代升级即将到来

    升级公告:由社区推动的cBridge 2.0功能迭代升级即将到来我们将在北京时间2021年12月3日上午10点推出cBridge2.0的一次功能迭代升级,以满足我们用户和开发者社区提出的一些关键功能需求。此次升级旨在让cBridge2.0更好地为通用的多链dApps和原生资产跨链桥接提供支持。升级期间,cBridge跨链转账服务会暂停约3小时。作为此次升级的一部分,所有LP需要迁移已提供的全部流动性。我们将为LP提供足够的gastoken以支付cBridge2.0目前已支持的链上的全部迁移成本,大家不必担心手续费的问题。迁移可以在升级前…

    2022年5月4日
    57
  • web api 学习 索引

    web api 学习 索引

    2021年9月13日
    48
  • 网络层传输层(计算机网络传输层大题)

    概述传输层的意义网络层可以把数据从一个主机传送到另一个主机,但是没有和进程建立联系。传输层就是讲进程和收到的数据联系到一起,使数据能够为应用服务所以说传输层是主机才有的层次传输层的两个协议传输层的寻址和端口端口号只用于计算机分辨本地进程,总共有2^16=65536种端口号,端口号有很多种,不能随便使用常见的应用程序端口号UDP协议UDP概述注释:因为UDP一次发送一个完整报文不会分片,所以需要应用层传输过来的数据不要太大,否则网络层分片任务就很重,但是也不能太小,不然效率较低

    2022年4月11日
    62

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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