xxl-job 应用代码小笔记

380 阅读3分钟

xxl-job的运行所需要的对象信息在xxl-job_info中,由update_match_state和update_match_step_state两个执行器分别控制赛事状态和赛事阶段状态。

赛事创建时会插入xxl-job所需要的赛事信息

@ApiOperation(value="新增", notes="根据情况新增")
@PostMapping("/save")
@Authority("match:info:add")
@Tracker(value = "赛事新增",operation = "赛事模块")
public CommonResult save(@RequestBody String jsonStr ){
    MatchInfoAndStepVO matchInfoAndStepVO = JSONObject.parseObject(jsonStr, MatchInfoAndStepVO.class);
    MatchInformationRequest matchInformationRequest=matchInfoAndStepVO.getMatchInformationRequest();
    String msg = matchInformationService.save(matchInformationRequest, matchInfoAndStepVO);
    try {
        this.updateMatchByXxl(matchInfoAndStepVO);
    }catch (ParseException e){
        throw new BizException("赛事定时任务cron表达式解析异常");
    }

通过updateMatchByXxl()方法,代码如下,比赛状态info中报名开始时间为TriggerNextTime,比赛阶段状态中最早的阶段开始时间为TriggerNextTime

private void updateMatchByXxl(MatchInfoAndStepVO matchInfoAndStepVO) throws ParseException {
    List<MatchInformation> matchInformations = matchInformationMapper.findByMatchName(matchInfoAndStepVO.getMatchInformationRequest().getMatchName());
    if (matchInformations != null && matchInformations.size() == 1){
        MatchInformation matchInformation = matchInformations.get(0);
        long registerStartTime = matchInformation.getRegisterStartTime().getTime();
        String jobDesc = "更新赛事状态任务"+matchInformation.getMatchId();
        //更新赛事
        insertIntoXxlJob(matchInformation.getMatchId(),registerStartTime,jobDesc,Constant.UPDATE_MATCH_STATE);
        //更新step
        ArrayList<Long> stepStateTriggerList = getStepStateTriggerList(matchInfoAndStepVO);
        Long minTime = Collections.min(stepStateTriggerList);
        insertIntoXxlJob(matchInformation.getMatchId(),minTime,"更新赛事阶段状态"+matchInformation.getMatchId(), Constant.UPDATE_MATCH_STEP_STATE);
    }
}

insertIntoXxlJob代码如下,设定赛事id、handle执行器、TriggerStatus(1),1为工具启动的状态、TriggerNextTime。

private void insertIntoXxlJob(Integer matchId,Long nextTime,String jobDesc,String handler) throws ParseException {
    XxlJobInfo xxlJobInfo = new XxlJobInfo();
    xxlJobInfo.setJobGroup(1);
    xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(nextTime)));
    xxlJobInfo.setJobDesc(jobDesc);
    xxlJobInfo.setAddTime(LocalDateTime.now());
    xxlJobInfo.setUpdateTime(LocalDateTime.now());
    xxlJobInfo.setAuthor("JW");
    xxlJobInfo.setExecutorRouteStrategy("FIRST");
    xxlJobInfo.setExecutorHandler(handler);
    xxlJobInfo.setExecutorParam(matchId.toString());
    xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
    xxlJobInfo.setExecutorTimeout(1000);
    xxlJobInfo.setExecutorFailRetryCount(2);
    xxlJobInfo.setGlueType("BEAN");
    xxlJobInfo.setGlueRemark("GLUE代码初始化");
    xxlJobInfo.setGlueUpdatetime(LocalDateTime.now());
    xxlJobInfo.setTriggerStatus(1);
    xxlJobInfo.setTriggerLastTime(0L);
    xxlJobInfo.setTriggerNextTime(nextTime);
    xxlJobInfoMapper.insert(xxlJobInfo);
}

如下为info数据库

image-20210313193338888.png

image-20210313200258885.png

如下为两个handle执行器

@XxlJob(Constant.UPDATE_MATCH_STATE)
public ReturnT<String> updateMatchState(String param) throws Exception{
    XxlJobLogger.log("开始更新赛事状态");
    platformJobManager.updateMatchState(param);
    XxlJobLogger.log("赛事状态更新结束");
    return ReturnT.SUCCESS;
}

@XxlJob(Constant.UPDATE_MATCH_STEP_STATE)
public ReturnT<String> updateMatchStepState(String param) throws Exception{
    XxlJobLogger.log("开始更新赛事阶段状态");
    platformJobManager.updateMatchStepState(param);
    XxlJobLogger.log("赛事阶段状态更新结束");
    return ReturnT.SUCCESS;

举赛事状态handle为栗子,查询info中对应赛事与执行器的info信息,查询赛事中的报名开始、结束,比赛开始、结束的时间,再与当前时间进行比较,分为5个阶段,判断状态、生成cron(时间点的一种表现形式)、TriggerNextTime、TriggerStatus(1)(因为status字段默认0,在更新插入info时,若不设定则为0,则工具停止,到下一阶段则并未启动)。

MatchState handle如下

@Override
public void updateMatchState(String param) throws ParseException {
    MatchInformation matchInformation = matchInformationMapper.selectByPrimaryKey(Integer.valueOf(param));
    XxlJobInfo xxlJobInfo = xxlJobInfoMapper.selectOne(new LambdaQueryWrapper<XxlJobInfo>().eq(XxlJobInfo::getExecutorParam,param)
    .eq(XxlJobInfo::getExecutorHandler,Constant.UPDATE_MATCH_STATE));
    if (matchInformation == null){
        log.error("找不到对应赛事,match_id = {}",Integer.valueOf(param));
        return;
    }
    long registerStartTime = matchInformation.getRegisterStartTime().getTime();
    long registerEndTime = matchInformation.getRegisterEndTime().getTime();
    long matchStartTime = matchInformation.getMatchStartTime().getTime();
    long matchEndTime = matchInformation.getMatchEndTime().getTime();
    long now = System.currentTimeMillis();
    if (now < registerStartTime){
        matchInformation.setMatchState(1);
        xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(registerStartTime)));
        xxlJobInfo.setTriggerNextTime(registerStartTime);
        xxlJobInfo.setTriggerStatus(1);
    }
    if (now >= registerStartTime && now < registerEndTime){
        matchInformation.setMatchState(2);
        xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(registerEndTime)));
        xxlJobInfo.setTriggerNextTime(registerEndTime);
        xxlJobInfo.setTriggerStatus(1);
    }
    if (now >= registerEndTime && now < matchStartTime){
        matchInformation.setMatchState(3);
        xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(matchStartTime)));
        xxlJobInfo.setTriggerNextTime(matchStartTime);
        xxlJobInfo.setTriggerStatus(1);
    }
    if (now >= matchStartTime && now < matchEndTime){
        matchInformation.setMatchState(4);
        xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(matchEndTime)));
        xxlJobInfo.setTriggerNextTime(matchEndTime);
        xxlJobInfo.setTriggerStatus(1);
    }
    if (now >= matchEndTime){
        matchInformation.setMatchState(5);
        xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(matchEndTime)));
        xxlJobInfo.setTriggerNextTime(matchEndTime);
        xxlJobInfo.setTriggerStatus(0);
    }
    xxlJobInfo.setUpdateTime(LocalDateTime.now());
    xxlJobInfo.setTriggerLastTime(xxlJobInfo.getTriggerNextTime());
    matchInformationMapper.updateById(matchInformation);
    xxlJobInfoMapper.updateById(xxlJobInfo);
}

MatchStepState handle如下

@Override
public void updateMatchStepState(String param) throws ParseException {
    List<MatchStep> matchStep = matchStepMapper.selectList(new LambdaQueryWrapper<MatchStep>().eq(MatchStep::getMatchId,Integer.valueOf(param)));
    XxlJobInfo xxlJobInfo = xxlJobInfoMapper.selectOne(new LambdaQueryWrapper<XxlJobInfo>().eq(XxlJobInfo::getExecutorParam,param)
            .eq(XxlJobInfo::getExecutorHandler,Constant.UPDATE_MATCH_STEP_STATE));
    if (matchStep == null || matchStep.size() == 0){
        log.error("找不到对应赛事,match_id = {}",Integer.valueOf(param));
        return;
    }
    long now = System.currentTimeMillis();
    for (MatchStep step : matchStep){
        long startTime = step.getStartTime().getTime();
        long endTime = step.getEndTime().getTime();
        if (step.getMatchStep().equals(3)){
            continue;
        }
        if (now < startTime){
            step.setMatchStepState(1);
            xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(startTime)));
            xxlJobInfo.setTriggerNextTime(startTime);
            xxlJobInfo.setTriggerStatus(1);
        }
        if (now >= startTime && now < endTime){
            step.setMatchStepState(2);
            xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(endTime)));
            xxlJobInfo.setTriggerNextTime(endTime);
            xxlJobInfo.setTriggerStatus(1);
        }
        if (now >= endTime){
            step.setMatchStepState(3);
            xxlJobInfo.setJobCron(CronUtil.getCronByOnce(new Date(endTime)));
            xxlJobInfo.setTriggerNextTime(endTime);
            // 最后一个阶段过后 stop触发器
            if(matchStep.size() - 1 == matchStep.indexOf(step)){
                xxlJobInfo.setTriggerStatus(0);
            }else {
                xxlJobInfo.setTriggerStatus(1);
            }
        }
        xxlJobInfo.setUpdateTime(LocalDateTime.now());
        xxlJobInfo.setTriggerLastTime(xxlJobInfo.getTriggerNextTime());
        matchStepMapper.updateById(step);
        xxlJobInfoMapper.updateById(xxlJobInfo);
    }

大致逻辑为:赛事创建和更新时会同时更新xxl-info的数据库的对应信息(cron和TriggerNextTime为下次状态更新时间,两个handle分别控制赛事状态和赛事阶段状态),到了对应时间,xxl-job组件内的handle执行器将执行各自任务对状态进行更新,更新后刷新下次更新需要的info。

如下为赛事修改

@ApiOperation(value="修改", notes="根据情况修改")
@PostMapping("/update")
@Authority("match:info:update")
@Tracker(value = "赛事修改",operation = "赛事模块")
public CommonResult update(@RequestBody String jsonStr){
    MatchInfoAndStepVO matchInfoAndStepVO = JSONObject.parseObject(jsonStr, MatchInfoAndStepVO.class);
    MatchInformationRequest matchInformationRequest=matchInfoAndStepVO.getMatchInformationRequest();
    List<MatchStepRequest> matchStepRequests = matchInfoAndStepVO.getMatchStepRequests();
    matchInformationService.update(matchInformationRequest,matchStepRequests);
    try {
        this.updateXxl(matchInfoAndStepVO);
    }catch (ParseException e){
        throw new BizException("赛事定时任务cron表达式解析异常");
    }
    return ResultUtil.success(ResultCode.SUCCESS);
}

updatexxl,查询修改的赛事信息,并将信息时间与下次更新时间进行比较判定,修改下次更新时间。

/**
 * 更新触发定时任务时间
 */
private void updateXxl(MatchInfoAndStepVO matchInfoAndStepVO) throws ParseException {
    MatchInformation matchInformation = null;
    if (matchInfoAndStepVO.getMatchInformationRequest().getMatchId() != null){
        matchInformation = matchInformationMapper.selectByPrimaryKey(matchInfoAndStepVO.getMatchInformationRequest().getMatchId());
    }else {
        matchInformation = matchInformationMapper.findByMatchName(matchInfoAndStepVO.getMatchInformationRequest().getMatchName()).get(0);
    }
    ArrayList<Long> matchStateTriggerList = getMatchStateTriggerList(matchInfoAndStepVO);
    ArrayList<Long> stepStateTriggerList = getStepStateTriggerList(matchInfoAndStepVO);

    long now = System.currentTimeMillis();

    XxlJobInfo match = xxlJobInfoMapper.selectOne(new LambdaQueryWrapper<XxlJobInfo>().eq(XxlJobInfo::getExecutorParam,matchInformation.getMatchId()).eq(XxlJobInfo::getExecutorHandler,Constant.UPDATE_MATCH_STATE));
    XxlJobInfo matchStep = xxlJobInfoMapper.selectOne(new LambdaQueryWrapper<XxlJobInfo>().eq(XxlJobInfo::getExecutorParam,matchInformation.getMatchId()).eq(XxlJobInfo::getExecutorHandler,Constant.UPDATE_MATCH_STEP_STATE));

    long thisMatchTime = match.getTriggerLastTime();
    long thisMatchStepTime =matchStep.getTriggerNextTime();

    for (Long aLong : matchStateTriggerList) {
        if (now < aLong && aLong < match.getTriggerNextTime()){
            match.setTriggerNextTime(aLong);
        }
    }
    if (match.getTriggerNextTime() != thisMatchTime){
        match.setJobCron(CronUtil.getCronByOnce(new Date(match.getTriggerNextTime())));
        xxlJobInfoMapper.updateById(match);
    }

    for (Long aLong : stepStateTriggerList) {
        if (now < aLong && aLong < matchStep.getTriggerNextTime()){
            matchStep.setTriggerNextTime(aLong);
        }
    }
    if (matchStep.getTriggerNextTime() != thisMatchStepTime){
        matchStep.setJobCron(CronUtil.getCronByOnce(new Date(matchStep.getTriggerNextTime())));
        xxlJobInfoMapper.updateById(matchStep);
    }