业务场景

需求上要求能实现quartz的simpleTrigger任务,同时还需要动态的创建任务而非在控制面板上创建,查阅xxl-job官方文档发现simpelTrigger其暂时还躺在to do list,而动态创建可以调用JobInfoController其add和start接口(但是有个弊端,start/stop/remove等方法都只要求传送id,这点上可以自己扩展接口实现),还需要放开登录权限,接下来就老夫上去就上一梭子,开干。

job_info字段调整说明

CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_cron` varchar(128) DEFAULT NULL COMMENT '任务执行CRON',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
`ext_reamrk` varchar(255) DEFAULT NULL,
`job_start_time` bigint(20) DEFAULT NULL COMMENT 'trigger开始时间于当前时间的时间间隔 单位毫秒\n',
`job_end_time` datetime DEFAULT NULL COMMENT 'trigger结束时间',
`job_repeat_count` bigint(7) DEFAULT '-1' COMMENT 'simple_trigger 执行次数 ',
`job_repeat_interval` bigint(12) DEFAULT NULL COMMENT 'simple_trigger 时间间隔 单位毫秒',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
  • job_cron设为空,支持simpleTrigger;
  • ext_reamrk自定义扩展字段,可以根据它来刷选job从而避免start/stop/remove接口只有id作为参数;
  • job_repeat_count,simplerTrigger的执行次数,默认-1即为无限次,0的话是执行1次;
  • job_repeat_interval,simplerTrigger每次执行的时间间隔,单位毫秒;
  • job_start_time,trigger开始时间和当前时间的时间间隔,单位毫秒;
  • job_end_time,trigger结束时间

重写启动任务

xxl-job在新建任务的时候只是把job数据保存到数据库里,只有启动的时候才会创建jobDetailtrigger并由scheduler来启动job。

重写XxlJobDynamicScheduleraddJob方法:根据jobInfo中的值构建cron的trigger还是simple的trigger。

public static boolean addJob(XxlJobInfo xxlJobInfo) throws SchedulerException {
String jobName = String.valueOf(xxlJobInfo.getId());
String cronExpression = xxlJobInfo.getJobCron();
Integer jobRepeatCount = xxlJobInfo.getJobRepeatCount();
Long jobRepeatInterval = xxlJobInfo.getJobRepeatInterval(); // 1、job key
TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
JobKey jobKey = new JobKey(jobName); // 2、valid trigger
if(scheduler.checkExists(triggerKey)) {
return true;
} // 3.1、corn trigger
Trigger trigger = null;
if (!StringUtils.isEmpty(cronExpression)) {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing(); // withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
TriggerBuilder<CronTrigger> builder = TriggerBuilder.newTrigger().withIdentity(triggerKey)
.withSchedule(cronScheduleBuilder)
.endAt(xxlJobInfo.getJobEndTime());
Optional.ofNullable(xxlJobInfo.getJobStartTime())
.ifPresent(start -> builder.startAt(new Date(System.currentTimeMillis() + start)));
trigger = builder.build();
} else
// 3.2、simple trigger
if (Objects.nonNull(jobRepeatInterval) && Objects.nonNull(jobRepeatCount)) {
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(jobRepeatInterval)
.withRepeatCount(jobRepeatCount);
TriggerBuilder<SimpleTrigger> builder = TriggerBuilder.newTrigger().withIdentity(triggerKey)
.withSchedule(simpleScheduleBuilder)
.endAt(xxlJobInfo.getJobEndTime());
Optional.ofNullable(xxlJobInfo.getJobStartTime())
.ifPresent(start -> builder.startAt(new Date(System.currentTimeMillis() + start)));
trigger = builder.build();
}
// 3.3、valid trigger
if(Objects.isNull(trigger)) {
return true;
} // 4、job detail
Class<? extends Job> jobClass_ = RemoteHttpJobBean.class; // Class.forName(jobInfo.getJobClass());
JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build(); /*if (jobInfo.getJobData()!=null) {
JobDataMap jobDataMap = jobDetail.getJobDataMap();
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
// JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
}*/ // 5、schedule job
Date date = scheduler.scheduleJob(jobDetail, trigger); logger.info(">>>>>>>>>>> addJob success(quartz), jobDetail:{}, trigger:{}, date:{}", jobDetail, trigger, date);
return true;
}

效果图

可以看到将数据库里3任务改为间隔3秒,job_repeat_count为1,任务实际会执行2次。

额外的工作

  1. 虽然支持cron或simple,但是在控制台节目只能维护cron的trigger,并且优先cron,同时cron设为可以为空,但是管理平台上没有simple的相关数据,如果需要的话要重新修改对应的页面和add和update的逻辑;
  2. job状态取的是trigger的状态,所以可能看到的是simpleTrigger的状态。
  3. 目前job的trigger是在cron和simple中二者取一,但是也可以扩展启动任务的方法,使其支持扩展多trigger,但是triggerKey需要重新定义而非取jobName(因为trigger的hash是triggerKey的hash),本身xxl-job的jobKey取的是job的id,triggerKey取的也是job的id,没有使用到groupName。

对xxl-job进行simpleTrigger并动态创建任务扩展的更多相关文章

  1. JavaScript dom 动态创建标记

    此前的大多数DOM都是用来查找元素,getElementById和getElementsByTagName都可以方便快捷的找到文档中的某个或者某些特定的元素节点,这些元素随后可以用诸如setAttri ...

  2. ios动态创建类Class

    [Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...

  3. winform 用户控件、 动态创建添加控件、timer控件、控件联动

    用户控件: 相当于自定义的一个panel 里面可以放各种其他控件,并可以在后台一下调用整个此自定义控件. 使用方法:在项目上右键.添加.用户控件,之后用户控件的编辑与普通容器控件类似.如果要在后台往窗 ...

  4. python动态创建类的声明

    动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类 ...

  5. Python 动态创建函数【转】

    知乎上也有相似的问题 偶然碰到一个问题,初想是通过动态创建Python函数的方式来解决,于是调研了动态创建Python函数的方法. 定义lambda函数 在Python中定义lambda函数的写法很简 ...

  6. WinForm用户控件、动态创建添加控件、timer控件--2016年12月12日

    好文要顶 关注我 收藏该文 徐淳 关注 - 1 粉丝 - 3       0 0     用户控件: 通过布局将多个控件整合为一个控件,根据自己的需要进行修改,可对用户控件内的所有控件及控件属性进行修 ...

  7. 动态创建DAL层类的实例

    为了可扩展性,方便以后对于代码的修改维护,使用动态创建DAL层对象. 1.首先在webconfig中的configuration下添加配置项 <appSettings> <add k ...

  8. [转]android:动态创建多个按钮 及 批量设置监听

    之前投机取巧,先创建好多个按钮,再根据需要的数量进行部分隐藏,不过还是逃不过呀. 这样根本无法批量地 findId,批量地 设置监听. 所以今天还是认认真真地研究回“动态创建按钮”,终于,通过不断尝试 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (38) ------ 第七章 使用对象服务之动态创建连接字符串和从数据库读取模型

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第七章 使用对象服务 本章篇幅适中,对真实应用中的常见问题提供了切实可行的解决方案. ...

随机推荐

  1. 模拟LinkedList

    Linkedlist是一个集合容器,具有增删改查基本功能,本例中模拟增删查,对于修改,只需要将原节点处的val更新为新值即可,增加和删除在链表中速度是比较快的,查找,修改慢,因为要从头或者从尾开始遍历 ...

  2. LC 244. Shortest Word Distance II 【lock, Medium】

    Design a class which receives a list of words in the constructor, and implements a method that takes ...

  3. mongdb group聚合操作

    1.数据准备 [{"goods_id":1,"cat_id":4,"goods_name":"KD876"," ...

  4. flutter 切换tab后保留tab状态

    前言 最近在用flutter写一个小项目,在写主页面(底部导航栏+子页面)时遇到的一个问题:当点击底部item切换到另一页面, 再返回此页面时会重走它的initState方法(我们一般在initSta ...

  5. JMeter使用plugins插件进行服务器性能监控

    JMeter使用plugins插件进行服务器性能监控 性能测试时,我们的关注点有两部分 1 服务本身:并发响应时间 QPS 2 服务器的资源使用情况:cpu memory I/O disk等 JMet ...

  6. RxJava2实战---第五章 变换操作符和过滤操作符

    RxJava2实战---第五章 变换操作符和过滤操作符 RxJava的变换操作符主要包括以下几种: map():对序列的每一项都用一个函数来变换Observable发射的数据序列. flatMap() ...

  7. Linux Shell 中 > 和 >> 的异同点和应用场景

    Linux Shell 中 > 和 >> 的异同点和应用场景 > 和 >> 的异同点 举例说明(start.sh 为某个服务的启动脚本,start.log 为某服务 ...

  8. Python聚类算法之基本K均值实例详解

    Python聚类算法之基本K均值实例详解 本文实例讲述了Python聚类算法之基本K均值运算技巧.分享给大家供大家参考,具体如下: 基本K均值 :选择 K 个初始质心,其中 K 是用户指定的参数,即所 ...

  9. 重启 hdfs and yarn datanode

    1- start-all.sh and stop-all.sh: Used to start and stop hadoop daemons all at once. Issuing it on th ...

  10. 安装VMTool

    一.       安装VMTool 开启虚拟机,然后在VMware上选虚拟机->安装VMTool 如果提示光驱被占用就先用root登录 在命令行中挂载光盘   #mount /dev/cdrom ...