XXL-JOB逻辑自测及执行参数配置踩坑

news2024/12/22 10:09:29

概述

关于XXL-JOB的使用遇到的问题记录。对XXL-JOB不熟的,可以先参考分布式任务调度平台XXL-JOB深度实战

实战

业务DTO定义如下:

@Data
public class AdAccountDTO {
	private String accountId;
	/**
     * yyyy-MM-dd HH:mm:ss
     */
	private String startCreateTime;
    private String endCreateTime;
}

JobHandler定义如下:

@Slf4j
@Service
@JobHander(value = "accountDependBindJobHandler")
public class AccountDependBindJobHandler extends IJobHandler {

    @Resource
    private BaseService<AdAccountDTO, Void> accountDependBindService;

    @Override
    public ReturnT<String> execute(String... params) {
        try {
            log.info("accountDependBindJobHandler begin");
            AdAccountDTO account = new AdAccountDTO();
            account.setCreatorName("system");
            // 32行
            if (params.length > 0) {
                account.setStartCreateTime(params[0]);
            }
            if (params.length > 1) {
                // 广告主
                account.setAccountId(params[1]);
            }
            if (params.length > 2) {
                account.setEndCreateTime(params[2]);
            }
            log.info("accountDependBindJobHandler account: {}", JSONObject.toJSONString(account));
            accountDependBindService.execute(account);
            log.info("accountDependBindJobHandler end");
        } catch (Exception e) {
            log.error("accountDependBindJobHandler fail", e);
            return ReturnT.FAIL;
        }
        return ReturnT.SUCCESS;
    }
}

业务实现类AccountDependBindService,此处仅展示部分:

@Override
protected void business(BizContextVo<AdAccountDTO, Void> bizContextVo) {
    AdAccountDTO accountDTO = bizContextVo.getIn();
    String startDate = accountDTO.getStartCreateTime();
    String endDate = accountDTO.getEndCreateTime();
    boolean check = StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate) &&
            !DateUtils.isBefore(accountDTO.getStartCreateTime(), accountDTO.getEndCreateTime());
    if (check) {
        throw new BaseException("", "时间不匹配");
    }
    // 可以兼容startDate为null,"",及" "等情况
    check = StringUtils.isBlank(startDate);
    if (check) {
        // 默认跑数1天
        accountDTO.setStartCreateTime(DateUtils.formatDate(DateUtils.addDays(new Date(), -1), DateUtils.DATE_FORMAT_YMDHMS));
    }
    check = StringUtils.isBlank(endDate);
    if (check) {
        accountDTO.setEndCreateTime(DateUtils.getCurrentTime());
    }
    log.info("accountDependBindService account: {}", JSONObject.toJSONString(accountDTO));
    // 根据条件查询
    List<AdAccountDTO> accountList = advertiserMapper.selectAllNewAdvertiser(accountDTO);	
}

XXL-JOB任务配置如下:
在这里插入图片描述
想要实现的效果是,如果执行参数为空,则取当前时间-24小时的数据开始同步。如果参数不为空,支持1-3个参数,第一个参数是同步开始时间,第二个是同步的账户,第三个是同步结束时间。

问题

自测

因为代码的改动都是在本地,即开发环境。本地无法直接连接到测试环境的xxl-job系统,即在测试环境的xxl-job管理界面手动执行任务时,并不能把任务下发到我的localhost:8080调试环境,不能断点调试。也许xxl-job有这个功能,但是我并不知道。 参考下面的【本地调试】章节实现方案。

想要验证job代码的逻辑,有以下3种方式:

  1. 代码提交到Git,fat环境打包部署,手动执行Job,查看日志,查看数据表,验证功能逻辑;
  2. 写一个Controller,Controller和JobHandler都是调用同一个Service业务实现类;
  3. 写一个UT,测试JobHandler的逻辑,同时还可以验证执行参数。

方式1,效率最低,得反复修改代码,反复提交,反复部署;
方式2,如果前端用不到Controller里新增的接口,或者后端开发人员也不需要借助于接口来补数据,或者同步数据,则会造成无用代码冗余;

所以我们选择方式3。在\src\test\java目录下面新增一个UT测试类:

@RunWith(SpringRunner.class)
// 指定应用启动类
@SpringBootTest(classes = WebApplication.class)
public class JobHandlerTest {
    @Resource
    private AccountDependBindJobHandler accountDependBindJobHandler;

    @Test
    public void testAuto() {
    	// 模拟参数为空,null的情况
        // accountDependBindJobHandler.execute(null);
        // 模拟参数为空,empty的情况
        // String[] params = new String[]{};
        // 模拟2个参数的情况
        String[] params = new String[]{"2022-09-26", "34343434"};
        accountDependBindJobHandler.execute(params);
    }
}

本地调试

XXL-JOB的执行器管理页如下:
在这里插入图片描述
注册方式可以是自动注册,也可以是手动注册。我们应用由于其特殊性,只能使用手动注册。参考分布式任务调度平台XXL-JOB深度实战执行器章节。

我们不可能在本地搭建一套XXL-JOB管理平台,即:http://dev-xxljob.johnny.com/jobgroup。公司搭建有fat环境的一套平台:http://fat-xxljob.johnny.com/jobgroup。能不能通过fat-xxl-job来调度执行我们本地的代码,当然可以!

编辑执行器,修改机器地址,指向我的本机IP:
在这里插入图片描述
然后在页面点击执行任务,任务详情如下:
在这里插入图片描述
然后请求确实打到本地,停在断点处:
在这里插入图片描述
这个截图也说明,如果执行参数为空时,params参数是null,而不是空字符串。

注意:不能启动web应用!!!

参考上面的文章,那篇文章提到,这里再说明下:web应用模块用于把任务注册同步到XXL-JOB平台,里面没有这个JobHandler类;dataset才是JobHandler所在的应用模块,这也是为什么不能使用自动注册方式。

事实上,如果同时启动web和dataset两个应用模块。在XXL-JOB页面点击执行任务,会概率性出现调度失败的报错:
在这里插入图片描述
点击查看调度备注:
在这里插入图片描述
报错:找不到JobHandler。

执行参数配置

参考上面的UT类,模拟5种情况:

  1. 参数为null
  2. 参数为空字符串
  3. 1个参数
  4. 2个参数,多个参数直接使用英文逗号分隔
  5. 3个参数

情况1自测下来会有报错:

ERROR c.p.c.p.s.AccountDependBindJobHandler - accountDependBindJobHandler fail
java.lang.NullPointerException: null
	at com.johnny.cbd.platform.scheduled.AccountDependBindJobHandler.execute$original$Iu6X8Nnv(AccountDependBindJobHandler.java:32)
	at com.johnny.cbd.platform.scheduled.AccountDependBindJobHandler.execute$original$Iu6X8Nnv$accessor$aikoAyrI(AccountDependBindJobHandler.java)
	at com.johnny.cbd.platform.scheduled.AccountDependBindJobHandler$auxiliary$HcNstxGt.call(Unknown Source)
	at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:86)
	at com.johnny.cbd.platform.scheduled.AccountDependBindJobHandler.execute(AccountDependBindJobHandler.java)
	at com.johnny.job.core.thread.JobThread.run(JobThread.java:141)

代码优化如下:

if (params != null && params.length > 0) {
    account.setStartCreateTime(params[0]);
}
if (params != null && params.length > 1) {
    account.setAccountId(params[1]);
}
if (params != null && params.length > 2) {
    account.setEndCreateTime(params[2]);
}

XXL-JOB页面参数配置如果为空,就是上面的情况1,参考上面章节截图。

XXL-JOB页面参数能实现参数配置为空字符串吗?答案是:不能!!
在这里插入图片描述
在这里插入图片描述
当然改成双引号也不行!!!

改成双引号后,应用打印的日志:

INFO c.p.c.p.s.AccountDependBindJobHandler - accountDependBindJobHandler account: {"creatorName":"system","needPage":true,"offset":10,"pageSize":10,"start":0,"startCreateTime":"\"\""}

默认以当前时间为截至时间:

INFO c.p.c.p.s.a.AccountDependBindServiceImpl - accountDependBindService account: {"creatorName":"system","endCreateTime":"2022-09-26 13:00:20","needPage":true,"offset":10,"pageIndex":1,"pageSize":10,"start":0,"startCreateTime":"\"\""} 

前面没有提到mapper.xml方法:

<select id="selectAllNewAdvertiser" resultType="com.johnny.dto.AdAccountDTO">
    SELECT advertiser_id accountId, 4 as type FROM channel_advertiser_id WHERE isactive = 1
    <if test="status != null">
        and status = #{status}
    </if>
    <if test="accountId != null">
        AND advertiser_id = #{accountId}
    </if>
    <if test="startCreateTime != null">
        AND insert_time &gt;= #{startCreateTime}
    </if>
    <if test="endCreateTime != null">
        AND insert_time &lt;= #{endCreateTime}
    </if>
</select>

满足if条件:startCreateTime != null,拼接得到的SQL为:

SELECT advertiser_id accountId, 4 as type FROM channel_advertiser_id WHERE isactive = 1 and advertiser_id = '1740858985811982' and insert_time >= '""'

有日志为证:

2022-09-26 16:42:53,603 [main] DEBUG c.p.c.b.d.C.selectAllNewAdvertiser- ==>  Preparing: SELECT advertiser_id accountId, 4 as type FROM channel_advertiser_id WHERE isactive = 1 and status = ? AND advertiser_id = ? AND insert_time >= ? AND insert_time <= ? 
2022-09-26 16:42:53,827 [main] DEBUG c.p.c.b.d.C.selectAllNewAdvertiser- ==> Parameters: 1(Integer), 1740858985811982(String), ""(String), 2022-09-26 16:42:49(String)
2022-09-26 16:42:53,977 [main] DEBUG c.p.c.b.d.C.selectAllNewAdvertiser- <==      Total: 8

截图为证:
在这里插入图片描述
也就是说,我们在DataGrip上面看到虽然有Incorrect datetime value问题,但是MySQL会做隐式转换,还是可以查询出结果来。

注,MySQL版本:5.7.29-32-log。

另外3种参数配置case,没啥好说的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ThingBoard源码解析-缓存

配置 TB支持两种缓存&#xff1a;Caffeine和Redis,通过配置cache.type来指定使用哪种缓存。 位于 org.thingsboard.server.cache Caffeine 配置类&#xff1a;CaffeineCacheConfiguration Configuration ConditionalOnProperty(prefix "cache", value "t…

HTML CSS 个人网页设计 WEB前端大作业代码

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【计算机毕业设计】7.线上花店系统maven源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 随着互联网突飞猛进的发展及其对人们的生活产生至关重要的影响&#xff0c;线上购花&#xff0c;送货到家的购物方式受到了越来越多顾客的接受与喜爱。线上花卉小铺的设计与实现不仅可以带来更广泛的选择与实…

餐饮业如何现业绩突破性增长?

疫情反复无常&#xff0c;餐饮人每天都面临着极大的挑战&#xff1a;无法预测的关店通知、突如其来的禁止堂食命令......餐饮店客流减少&#xff0c;业绩下滑成为不可避免的趋势。 在这种情形下&#xff0c;不少餐饮老板拒绝“躺平”&#xff0c;上演“花式自救”&#xff1a;…

cpu设计和实现(数据预取)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面说过了一条指令经过cpu处理的时候需要经历几个阶段。通过实验&#xff0c;我们发现&#xff0c;哪怕是再简单的ori指令也要经历取指、译码、执…

MyBatis是什么?使用方式?

目录 前言&#xff1a; 一、概念讲述 1.什么是MyBatis&#xff1f; 2.官网网址 二、使用方式 1.pom.xml里面添加依赖包 2.新建统一配置文件&#xff08;俗称数据库连接文件&#xff09; 3.新建立映射文件 &#xff08;俗称数据库表对应xml&#xff09; 4.建立数据库表…

ArcMap中之提取影像数据边界

1、前言 手里有一些经过裁剪的不规则多边形影像数据&#xff08;如图例所示&#xff09;&#xff0c;希望能批量获取该类影像的边界信息&#xff0c;即影像对应的面信息&#xff0c;边界线信息。这里我们提供一种利用镶嵌数据集Footprint图层的方法来获取&#xff0c;面&#…

基于Python机器学习及深度学习在空间模拟与时间预测应用

了解机器学习的发展历史、计算原理、基本定义&#xff0c;熟悉机器学习方法的分类&#xff0c;常用机器学习方法&#xff0c;以及模型的评估与选择&#xff1b;熟悉数据预处理的流程&#xff0c;掌握python程序包的使用&#xff1b;理解机器学习在生态水文中的应用&#xff0c;…

超实用的图片处理技巧,一分钟轻松完成图片编辑

图片想必大家都很熟悉&#xff0c;无论是我们平时在聊天的时候使用的表情包或者是在工作中插入的插图都属于图片&#xff0c;在使用图片的时候大家会遇到各种各样的问题&#xff0c;比如上传的图片格式不对、使用的图片尺寸太大等等&#xff0c;都会导致图片无法正常使用&#…

[附源码]java毕业设计医院就诊流程管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

c++旅行商问题 (暴力解)

目录一、旅行商问题简介旅行商问题问题概述问题由来二、枚举所有方案1、思路2、代码3、复杂度分析三、深度优先搜索1、思路2、代码3、复杂度分析一、旅行商问题简介 旅行商问题 TSP&#xff0c;即旅行商问题&#xff0c;又称TSP问题&#xff08;Traveling Salesman Problem&am…

白盒测试与黑盒测试

白盒测试技术 白盒测试技术也称结构性测试&#xff0c;是一种设计测试用例的方法&#xff0c;一般用于分析程序的内部结构&#xff0c;使用该方法测试程序时测试者可以看到被测试程序&#xff0c;并分析其内部结构。 按照被测试测试时是否需要执行测试程序可以分为静态和动态…

RK3399平台开发系列讲解(中断篇)中断控制器驱动初始化

🚀返回专栏总目录 文章目录 一、设备树源文件1.1、gic控制器节点1.2、timer节点二、中断控制器匹配表三、中断控制器初始化3.1、函数of_irq_init3.2、函数gicv3_of_init3.3、函数gic_init_bases沉淀、分享、成长,让自己和他人都能有所收获!😄 一、设备树源文件 ARM64架构…

web前端网页制作课作业:甜甜圈蛋糕店(HTML+CSS+JavaScript)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

用DIV+CSS技术设计的水果介绍网站(web前端网页制作课作业)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

NodeJs实战-Express构建照片存储网站(2)-上传、展示文件

Express构建照片存储网站2-上传、展示文件静态资源显示图片photo页面展示文件夹下的图片上传文件增加上传页面的路由增加提交接口的路由网站效果图项目地址上一节使用的静态数据存储的图片的数据&#xff0c;本节增加如下功能 1–上传文件 2–展示文件 静态资源显示图片 app.…

企业微信自建应用手动授权,获取用户详细信息

开始开发 最后更新&#xff1a;2022/10/11 企业微信提供了OAuth的授权登录方式&#xff0c;可以让从企业微信终端打开的网页获取成员的身份信息&#xff0c;从而免去登录的环节。 企业应用中的URL链接&#xff08;包括自定义菜单或者消息中的链接&#xff09;&#xff0c;均可…

宇视高空抛物相机配置指导

宇视高空抛物相机配置指导 登录摄像机网页界面&#xff0c;进入[配置>智能监控>智能功能]页面启用<高空抛物>功能&#xff0c;并进入高空抛物配置界面&#xff1b; 添加/删除检测规则&#xff0c;根据实际高空抛物场景和规则下发要求绘制检测区域&#xff1b; (…

必看!!!客户端requests与服务端request收发请求

当使用代码进行接口访问的时候&#xff0c;请求的发送与请求的接受使用的参数应该怎么如何传输能够请求到正确的响应呢? 一、使用GET请求发送&#xff0c;客户端与服务端的参数传输与接受。 1、服务端&#xff0c;首先使用web框架写一个简单的接口&#xff0c;接收两个参数&…

FineReport常用配置和方法

目录 1、隐藏参数面板的小箭头&#xff1a; 1、隐藏参数面板的小箭头&#xff1a; 查看小箭头的class&#xff0c;css设置如下属性&#xff1a; 隐藏按钮&#xff1a; // 旧版 $(.parameter-container-collapseimg-up).hide(); // 新版 $(.report-main-parameter-container-…