XXL-JOB实现通过代码方式动态crud任务

3,000 阅读5分钟

动态crud任务

若还不知道怎么使用xxl-job,可以看我前一篇文章 XXL-JOB初步使用

XXL-JOB对任务配置非常方便,只需要启动调度中心就可以对任务进行任意配置。 但是如果我的需要需要动态的创建、删除、启用、停用等操作就有点乏力了。

我找了一圈发现文档里好像没有有关动态操作任务的说明,我想到的方式是,通过调用调度中心的任务相关接口实现在代码里动态操作任务。

大概的思路如下:

  • 对调度中心的任务相关接口进行封装,并放开权限,可直接访问。
  • 自身项目创建调用调度中心接口的工具类

封装调度中心接口

注解@PermissionLimit(limit = false)表示对该接口放行,不用登录就可以访问

JobInfoController (任务信息Controller)

@Controller
@RequestMapping("/jobinfo")
public class JobInfoController {
   //原有方法不改动

   /**
    * ------------------封装方法----------------------
    */

   /**
    * 新增任务
    * @param jobInfo 任务信息
    * @return 任务id
    */
   @RequestMapping("/addJob")
   @ResponseBody
   @PermissionLimit(limit = false)
   public ReturnT<String> addJob(@RequestBody XxlJobInfo jobInfo) {
      logger.info("addJob---param:[{}]",jobInfo);
      return xxlJobService.add(jobInfo);
   }

   /**
    * 修改任务
    * @param jobInfo 任务信息
    * @return
    */
   @RequestMapping("/updateJob")
   @ResponseBody
   @PermissionLimit(limit = false)
   public ReturnT<String> updateJob(@RequestBody XxlJobInfo jobInfo) {
      logger.info("updateJob---param:[{}]",jobInfo);
      return xxlJobService.update(jobInfo);
   }

   /**
    * 删除任务
    * @param jobInfo 任务
    * @return
    */
   @RequestMapping("/removeJob")
   @ResponseBody
   @PermissionLimit(limit = false)
   public ReturnT<String> removeJob(@RequestBody XxlJobInfo jobInfo) {
      logger.info("removeJob---param:[{}]",jobInfo);
      return xxlJobService.remove(jobInfo.getId());
   }

   /**
    * 停止任务
    * @param jobInfo 任务id
    * @return
    */
   @RequestMapping("/stopJob")
   @ResponseBody
   @PermissionLimit(limit = false)
   public ReturnT<String> stopJob(@RequestBody XxlJobInfo jobInfo) {
      logger.info("stopJob---param:[{}]",jobInfo);
      return xxlJobService.stop(jobInfo.getId());
   }

   /**
    * 启动任务
    * @param jobInfo 任务id
    * @return
    */
   @RequestMapping("/startJob")
   @ResponseBody
   @PermissionLimit(limit = false)
   public ReturnT<String> startJob(@RequestBody XxlJobInfo jobInfo) {
      logger.info("startJob---param:[{}]",jobInfo);
      return xxlJobService.start(jobInfo.getId());
   }

}

JobGroupController (执行器Controller)

这里添加一个通过执行器名称查询执行器id的接口,方便我们添加任务信息时,通过配置的执行器名称设置执行器id。只是一个基础查询方法,具体实现就不赘述了。

@Controller
@RequestMapping("/jobgroup")
public class JobGroupController {
   //原有方法不改动

   /**
    * ------------------封装方法----------------------
    */
   /**
    * 根据执行器名称,查询执行器id
    * @param jobGroup 执行器信息
    * @return 执行器id
    */
   @RequestMapping("/getGroupId")
   @ResponseBody
   @PermissionLimit(limit = false)
   public ReturnT<String> getGroupId(@RequestBody XxlJobGroup jobGroup) {
      logger.info("getGroupId---param:[{}]",jobGroup);
      XxlJobGroup group = xxlJobGroupDao.findByName(jobGroup.getAppname());
      return new ReturnT<String>(String.valueOf(group.getId()));
   }

}

自身项目修改

按照我之前的那篇文章,将自己的项目用作执行器配置 XXL-JOB初步使用

在此基础上虽然可以通过调度中心配置任务,但是动态配置任务还是没能实现。

我们需要重新写一个工具类来调用调度中心的任务的相关接口,实现动态crud任务信息。

XxlJobUtil

@Slf4j
@Component
public class XxlJobUtil {

    /**
     * 调度中心地址
     */
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    /**
     * 执行器名称
     */
    @Value("${xxl.job.executor.appname}")
    private String appname;

    private RestTemplate restTemplate = new RestTemplate();

    private static final String ADD_URL = "/jobinfo/addJob";
    private static final String UPDATE_URL = "/jobinfo/updateJob";
    private static final String REMOVE_URL = "/jobinfo/removeJob";
    private static final String STOP_URL = "/jobinfo/stopJob";
    private static final String START_URL = "/jobinfo/startJob";
    private static final String GET_GROUP_ID = "/jobgroup/getGroupId";

    /**
     * 获取执行器id
     * @return 执行器id
     */
    public Integer getGroupId(){
        // 查询对应groupId:
        Map<String, Object> param = new HashMap<>();
        param.put("appname", appname);
        String json = JSON.toJSONString(param);
        //根据执行器名称,获取执行器id
        String result = doPost(adminAddresses + GET_GROUP_ID, json);
        return Integer.parseInt( JSON.parseObject(result).getString("content") );
    }

    /**
     * 新建任务
     * @param jobInfo 任务信息
     * @return {"code":200,"msg":null,"content":"3"} content:任务id
     */
    public String add(XxlJobInfo jobInfo) {
        jobInfo.setJobGroup(getGroupId());
        String json2 = JSON.toJSONString(jobInfo);
        //新建任务
        return doPost(adminAddresses + ADD_URL, json2);
    }

    /**
     * 修改任务
     * @param jobInfo 任务信息
     * @return {"code":200,"msg":null,"content":null}
     */
    public String update(XxlJobInfo jobInfo) {
        jobInfo.setJobGroup(getGroupId());
        String json2 = JSON.toJSONString(jobInfo);
        return doPost(adminAddresses + UPDATE_URL, json2);
    }

    /**
     * 删除任务
     * @param id 任务id
     * @return {"code":200,"msg":null,"content":null}
     */
    public String remove(int id) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + REMOVE_URL, json);
    }

    /**
     * 停止任务
     * @param id 任务id
     * @return {"code":200,"msg":null,"content":null}
     */
    public String stop(int id) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + STOP_URL, json);
    }

    /**
     * 启动任务
     * @param id 任务id
     * @return {"code":200,"msg":null,"content":null}
     */
    public String start(int id) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + START_URL, json);
    }

    /**
     * 调用任务调度中心接口
     * @param url 调度中心地址
     * @param json json字符串参数
     * @return
     */
    public String doPost(String url, String json) {
        HttpHeaders headers = new HttpHeaders();
        //必须指定utf-8格式,不然调度中心接受中文为乱码
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> entity = new HttpEntity<>(json, headers);
        //调用任务调度中心接口
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, entity, String.class);
        return stringResponseEntity.getBody();
    }
}

拷贝一份调度中心代码中用于封装任务的任务信息对象 XxlJobInfo ,不用做任何修改,和调度中心的保持一致。

XxlJobInfo

/**
 * xxl-job 任务信息
 **/
public class XxlJobInfo {

   private int id;             // 主键ID

   private int jobGroup;     // 执行器主键ID
   private String jobDesc;

   private Date addTime;
   private Date updateTime;

   private String author;    // 负责人
   private String alarmEmail; // 报警邮件

   private String scheduleType;         // 调度类型
   private String scheduleConf;         // 调度配置,值含义取决于调度类型
   private String misfireStrategy;          // 调度过期策略

   private String executorRouteStrategy;  // 执行器路由策略
   private String executorHandler;           // 执行器,任务Handler名称
   private String executorParam;         // 执行器,任务参数
   private String executorBlockStrategy;  // 阻塞处理策略
   private int executorTimeout;          // 任务执行超时时间,单位秒
   private int executorFailRetryCount;       // 失败重试次数

   private String glueType;      // GLUE类型  #com.xxl.job.core.glue.GlueTypeEnum
   private String glueSource;    // GLUE源代码
   private String glueRemark;    // GLUE备注
   private Date glueUpdatetime;   // GLUE更新时间

   private String childJobId;    // 子任务ID,多个逗号分隔

   private int triggerStatus;    // 调度状态:0-停止,1-运行
   private long triggerLastTime;  // 上次调度时间
   private long triggerNextTime;  // 下次调度时间


   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public int getJobGroup() {
      return jobGroup;
   }

   public void setJobGroup(int jobGroup) {
      this.jobGroup = jobGroup;
   }

   public String getJobDesc() {
      return jobDesc;
   }

   public void setJobDesc(String jobDesc) {
      this.jobDesc = jobDesc;
   }

   public Date getAddTime() {
      return addTime;
   }

   public void setAddTime(Date addTime) {
      this.addTime = addTime;
   }

   public Date getUpdateTime() {
      return updateTime;
   }

   public void setUpdateTime(Date updateTime) {
      this.updateTime = updateTime;
   }

   public String getAuthor() {
      return author;
   }

   public void setAuthor(String author) {
      this.author = author;
   }

   public String getAlarmEmail() {
      return alarmEmail;
   }

   public void setAlarmEmail(String alarmEmail) {
      this.alarmEmail = alarmEmail;
   }

   public String getScheduleType() {
      return scheduleType;
   }

   public void setScheduleType(String scheduleType) {
      this.scheduleType = scheduleType;
   }

   public String getScheduleConf() {
      return scheduleConf;
   }

   public void setScheduleConf(String scheduleConf) {
      this.scheduleConf = scheduleConf;
   }

   public String getMisfireStrategy() {
      return misfireStrategy;
   }

   public void setMisfireStrategy(String misfireStrategy) {
      this.misfireStrategy = misfireStrategy;
   }

   public String getExecutorRouteStrategy() {
      return executorRouteStrategy;
   }

   public void setExecutorRouteStrategy(String executorRouteStrategy) {
      this.executorRouteStrategy = executorRouteStrategy;
   }

   public String getExecutorHandler() {
      return executorHandler;
   }

   public void setExecutorHandler(String executorHandler) {
      this.executorHandler = executorHandler;
   }

   public String getExecutorParam() {
      return executorParam;
   }

   public void setExecutorParam(String executorParam) {
      this.executorParam = executorParam;
   }

   public String getExecutorBlockStrategy() {
      return executorBlockStrategy;
   }

   public void setExecutorBlockStrategy(String executorBlockStrategy) {
      this.executorBlockStrategy = executorBlockStrategy;
   }

   public int getExecutorTimeout() {
      return executorTimeout;
   }

   public void setExecutorTimeout(int executorTimeout) {
      this.executorTimeout = executorTimeout;
   }

   public int getExecutorFailRetryCount() {
      return executorFailRetryCount;
   }

   public void setExecutorFailRetryCount(int executorFailRetryCount) {
      this.executorFailRetryCount = executorFailRetryCount;
   }

   public String getGlueType() {
      return glueType;
   }

   public void setGlueType(String glueType) {
      this.glueType = glueType;
   }

   public String getGlueSource() {
      return glueSource;
   }

   public void setGlueSource(String glueSource) {
      this.glueSource = glueSource;
   }

   public String getGlueRemark() {
      return glueRemark;
   }

   public void setGlueRemark(String glueRemark) {
      this.glueRemark = glueRemark;
   }

   public Date getGlueUpdatetime() {
      return glueUpdatetime;
   }

   public void setGlueUpdatetime(Date glueUpdatetime) {
      this.glueUpdatetime = glueUpdatetime;
   }

   public String getChildJobId() {
      return childJobId;
   }

   public void setChildJobId(String childJobId) {
      this.childJobId = childJobId;
   }

   public int getTriggerStatus() {
      return triggerStatus;
   }

   public void setTriggerStatus(int triggerStatus) {
      this.triggerStatus = triggerStatus;
   }

   public long getTriggerLastTime() {
      return triggerLastTime;
   }

   public void setTriggerLastTime(long triggerLastTime) {
      this.triggerLastTime = triggerLastTime;
   }

   public long getTriggerNextTime() {
      return triggerNextTime;
   }

   public void setTriggerNextTime(long triggerNextTime) {
      this.triggerNextTime = triggerNextTime;
   }

   @Override
   public String toString() {
      return "XxlJobInfo{" +
            "id=" + id +
            ", jobGroup=" + jobGroup +
            ", jobDesc='" + jobDesc + ''' +
            ", addTime=" + addTime +
            ", updateTime=" + updateTime +
            ", author='" + author + ''' +
            ", alarmEmail='" + alarmEmail + ''' +
            ", scheduleType='" + scheduleType + ''' +
            ", scheduleConf='" + scheduleConf + ''' +
            ", misfireStrategy='" + misfireStrategy + ''' +
            ", executorRouteStrategy='" + executorRouteStrategy + ''' +
            ", executorHandler='" + executorHandler + ''' +
            ", executorParam='" + executorParam + ''' +
            ", executorBlockStrategy='" + executorBlockStrategy + ''' +
            ", executorTimeout=" + executorTimeout +
            ", executorFailRetryCount=" + executorFailRetryCount +
            ", glueType='" + glueType + ''' +
            ", glueSource='" + glueSource + ''' +
            ", glueRemark='" + glueRemark + ''' +
            ", glueUpdatetime=" + glueUpdatetime +
            ", childJobId='" + childJobId + ''' +
            ", triggerStatus=" + triggerStatus +
            ", triggerLastTime=" + triggerLastTime +
            ", triggerNextTime=" + triggerNextTime +
            '}';
   }
}

到这里其实我们就可以对任务进行crud了。 只需要封装任务信息对象 XxlJobInfo ,调用对应工具类接口就行。

不知道具体传什么的话,就在调度中心调用相应接口,F12调试窗口看具体传了什么东西。

参考文章


认真做好每件事,慢一点才能更快