手动执行任务

页面上点击“执行” 按钮, 前端会发送一个请求 /jobinfo/trigger   post 请求

param: id = 任务ID

controller最终会调用service的方法进行处理

public ReturnT<String> triggerJob(int id) {

        // 从数据库中查询该任务的具体信息

        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);

       if (xxlJobInfo == null) {

           return new ReturnT<String>(ReturnT.FAIL_CODE, "任务不存在" );

        }

       String group = String.valueOf(xxlJobInfo.getJobGroup());

       String name = String.valueOf(xxlJobInfo.getId());

   try {

        // 调用执行器类,触发该任务 ,

      XxlJobDynamicScheduler.triggerJob(name, group);

      return ReturnT.SUCCESS;

   catch (SchedulerException e) {

      logger.error(e.getMessage(), e);

      return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());

   }

}

// XxlJobDynamicScheduler 中的triggerJob方法

public static boolean triggerJob(String jobName, String jobGroup) throws SchedulerException {

   // TriggerKey : name + group

   JobKey jobKey = new JobKey(jobName, jobGroup);

    

    boolean result = false;

    if (checkExists(jobName, jobGroup)) {

        // 调用quartz的Scheduler来触发任务

        scheduler.triggerJob(jobKey);

        result = true;

        logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);

    else {

       logger.info(">>>>>>>>>>> runJob fail, jobKey:{}", jobKey);

    }

    return result;

}

暂停任务

页面上点击“暂停” 按钮, 前端会发送一个请求 /jobinfo/pause  post 请求

param: id = 任务ID

controller最终会调用service的方法进行处理

XxlJobServiceImpl

@Override

public ReturnT<String> pause(int id) {

        // 从数据库中获取任务信息,主要是为了获取group和name, 这个是组成在quartz里面的定时器的key

       XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);

       String group = String.valueOf(xxlJobInfo.getJobGroup());

       String name = String.valueOf(xxlJobInfo.getId());

   try {

           // 调用quartz操作类来暂停任务

           boolean ret = XxlJobDynamicScheduler.pauseJob(name, group); //

           return ret?ReturnT.SUCCESS:ReturnT.FAIL;

   catch (SchedulerException e) {

      logger.error(e.getMessage(), e);

      return ReturnT.FAIL;

   }

}

// XxlJobDynamicScheduler 中的pauseJob方法

public static boolean pauseJob(String jobName, String jobGroup) throws SchedulerException {

   // TriggerKey : name + group

   TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

    

    boolean result = false;

    if (checkExists(jobName, jobGroup)) {

        // 暂停任务

        scheduler.pauseTrigger(triggerKey);

        result = true;

        logger.info(">>>>>>>>>>> pauseJob success, triggerKey:{}", triggerKey);

    else {

       logger.info(">>>>>>>>>>> pauseJob fail, triggerKey:{}", triggerKey);

    }

    return result;

}

恢复任务

页面上点击“恢复” 按钮, 前端会发送一个请求 /jobinfo/resume  post 请求

param: id = 任务ID

controller最终会调用service的方法进行处理

XxlJobServiceImpl

@Override

public ReturnT<String> resume(int id) {

        // 从数据库中获取任务信息,主要是为了获取group和name, 这个是组成在quartz里面的定时器的key

       XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);

       String group = String.valueOf(xxlJobInfo.getJobGroup());

       String name = String.valueOf(xxlJobInfo.getId());

   try {

    // 恢复任务

      boolean ret = XxlJobDynamicScheduler.resumeJob(name, group);

      return ret?ReturnT.SUCCESS:ReturnT.FAIL;

   catch (SchedulerException e) {

      logger.error(e.getMessage(), e);

      return ReturnT.FAIL;

   }

}

// XxlJobDynamicScheduler 中的resumeJob方法

public static boolean resumeJob(String jobName, String jobGroup) throws SchedulerException {

   // TriggerKey : name + group

   TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

    

    boolean result = false;

    if (checkExists(jobName, jobGroup)) {

        // 暂停任务

        scheduler.resumeTrigger(triggerKey);

        result = true;

        logger.info(">>>>>>>>>>> resumeJob success, triggerKey:{}", triggerKey);

    else {

       logger.info(">>>>>>>>>>> resumeJob fail, triggerKey:{}", triggerKey);

    }

    return result;

}

删除任务

页面上点击“执行” 按钮, 前端会发送一个请求 /jobinfo/remove  post 请求

param: id = 任务ID

controller最终会调用service的方法进行处理

XxlJobServiceImpl

public ReturnT<String> remove(int id) {

   XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);

       String group = String.valueOf(xxlJobInfo.getJobGroup());

       String name = String.valueOf(xxlJobInfo.getId());

   try {

     //调用quartz删除他内置的定时器

      XxlJobDynamicScheduler.removeJob(name, group);

      // 删除数据库中的任务

      xxlJobInfoDao.delete(id);

      // 删除调度日志

      xxlJobLogDao.delete(id);

      // 如果是脚本类型的任务,则删除脚本变化日志

      xxlJobLogGlueDao.deleteByJobId(id);

      return ReturnT.SUCCESS;

   catch (SchedulerException e) {

      logger.error(e.getMessage(), e);

   }

   return ReturnT.FAIL;

}

终止任务

在调度日志的日志列表页面,正在执行者中的任务,可以手动进行终止。 前端会发送  /joblog/logKill? id= 日志ID

JobLogController

@RequestMapping("/logKill")

@ResponseBody

public ReturnT<String> logKill(int id){

   // 从数据库中获取该日志信息

   XxlJobLog log = xxlJobLogDao.load(id);

  // 获取该任务的信息

   XxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());

   if (jobInfo==null) {

      return new ReturnT<String>(500"任务不存在");

   }

   if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {

      return new ReturnT<String>(500"任务没有触发成功,无需终止");

   }

   // request of kill

   ReturnT<String> runResult = null;

   try {

      // 通过NetComClientProxy创建代理对象,代理对象invoke方法里面包含了HTTP请求,会将该请求发送至执行器那一端。

      // 通过执行器来终止该任务 , 下面主要来看一下执行器那边的kill方法。

      ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(log.getExecutorAddress());

      runResult = executorBiz.kill(jobInfo.getId());

   catch (Exception e) {

      logger.error(e.getMessage(), e);

      runResult = new ReturnT<String>(500, e.getMessage());

   }

   if (ReturnT.SUCCESS_CODE == runResult.getCode()) {

      log.setHandleCode(ReturnT.FAIL_CODE);

      log.setHandleMsg( I18nUtil.getString("joblog_kill_log_byman")+":" + (runResult.getMsg()!=null?runResult.getMsg():""));

      log.setHandleTime(new Date());

      xxlJobLogDao.updateHandleInfo(log);

      return new ReturnT<String>(runResult.getMsg());

   else {

      return new ReturnT<String>(500, runResult.getMsg());

   }

}

ExecutorBizImpl

@Override

public ReturnT<String> kill(int jobId) {

    // 从线程池里面根据该任务ID,获取对应的线程

    JobThread jobThread = XxlJobExecutor.loadJobThread(jobId);

    if (jobThread != null) {

        // 线程存在,则手动移除 ,下面可以看一下remove方法

        XxlJobExecutor.removeJobThread(jobId, "人工手动终止");

        return ReturnT.SUCCESS;

    }

    return new ReturnT<String>(ReturnT.SUCCESS_CODE, "job thread aleady killed.");

}

public static void removeJobThread(int jobId, String removeOldReason){

    // 从线程池(ConcurrentHashMap)中移除该队列

    JobThread oldJobThread = JobThreadRepository.remove(jobId);

    if (oldJobThread != null) {

        //发送stop信息,线程的run方法,发现该信息,则会停止运行,并记录日志

        oldJobThread.toStop(removeOldReason);

        // 发送中断信息

        oldJobThread.interrupt();

    }

}

sharedCode源码交流群,欢迎喜欢阅读源码的朋友加群,添加下面的微信, 备注”加群“ 。

xxl-job任务操作源码分析(四)相关推荐

  1. 【投屏】Scrcpy源码分析四(最终章 - Server篇)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  2. ABP源码分析四十七:ABP中的异常处理

    ABP源码分析四十七:ABP中的异常处理 参考文章: (1)ABP源码分析四十七:ABP中的异常处理 (2)https://www.cnblogs.com/1zhk/p/5538983.html (3 ...

  3. gSOAP 源码分析(四)

    gSOAP 源码分析(四) 2012-6-2 邵盛松 前言 本文主要说明gSOAP中对Client的认证分析 gSOAP中包含了HTTP基本认证,NTLM认证等,还可以自定义SOAP Heard实现认 ...

  4. Spring 源码分析(四) ——MVC(二)概述

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) from:Spring 源码分析(四) --MVC(二)概述 - 水门-kay的个人页面 - OSCHINA ...

  5. 【转】ABP源码分析四十七:ABP中的异常处理

    ABP 中异常处理的思路是很清晰的.一共五种类型的异常类. AbpInitializationException用于封装ABP初始化过程中出现的异常,只要抛出AbpInitializationExce ...

  6. 【转】ABP源码分析四十三:ZERO的本地化

    ABP Zero模块扩展了ABP基础框架中的本地化功能,实现了通过数据库对本地化功能进行管理.其通过数据库保存本地化语言及其资源. ApplicationLanguage:代表本地化语言的实体类.一种 ...

  7. 【转】ABP源码分析四十二:ZERO的身份认证

    ABP Zero模块通过自定义实现Asp.Net Identity完成身份认证功能, 对Asp.Net Identity做了较大幅度的扩展.同时重写了ABP核心模块中的permission功能,以实现 ...

  8. 【转】ABP源码分析四十一:ZERO的Audit,Setting,Background Job

    AuditLog: 继承自Entity<long>的实体类.封装AuditLog的信息. AuditingStore: 实现了IAuditingStore接口,实现了将AuditLog的信 ...

  9. 【转】ABP源码分析四十:ZERO的Application和Tenant

    ABP的Zero模块以数据库为数据源实现了ABP框架中的tenant management (multi-tenancy), role management, user management, ses ...

最新文章

  1. java 中pc寄存器的作用_既然有PC寄存器,栈帧里的返回地址的作用是什么?
  2. 佛山市禅城区计算机培训机构排名前十,佛山名气大的机器人编程教育品牌排名...
  3. SourceTree跳过Atlassian账号,免登陆,跳过初始设置
  4. 【log4j】—日志记录log4j的Logger和commons.logging的Log的区别
  5. Anti-Forgery Request Recipes For ASP.NET MVC And AJAX 防伪验证,防伪请求
  6. LightOJ 1370 Bi-shoe and Phi-shoe(欧拉函数)
  7. win10子linux如何重置密码,Win10如何使用Windows PowerShell命令重置本地账户密码
  8. 利用MAVEN的profile 实现打包环境的切换
  9. Linux问题处理————命令提示符显示 bash-4.1# 解决方案
  10. ssh不能连接 提示WARNING: POSSIBLE DNS SPOOFING DETECTED!处理方法
  11. mysql中字符串和数字的互转函数
  12. python第三十二天-----算法
  13. keras中文文档网址
  14. 数据库 无损分解和保持依赖的判断
  15. 数字和模拟混合供电20190221
  16. 水花兄弟(Splash Brothers)
  17. 3个基于 Spring Boot 的图片识别处理系统
  18. Ubuntu登录界面键盘鼠标失灵
  19. 实战内容(13)- Invalid audio stream. Exactly one MP3 audio stream is required.
  20. uni-app点击按钮弹出提示框-uni.showModal(OBJECT),选择确定和取消

热门文章

  1. 在PHP中implement什么意思,php 接口,extends,implement,implements 作用及区别收集整理
  2. 笔记本电脑无法无线上网 提示“区域中找不到无线网络”
  3. matlab加速度数据积分,android – MATLAB从加速度到速度到位置的积分时,我的y值非常高...
  4. 欧几里得与扩展欧几里得算法(含推导过程及代码)
  5. 家电巨头“竞技”医疗器械
  6. 刷题总结——支线剧情(bzoj3876费用流)
  7. native2ascii的用法
  8. 中秋国庆两节临近,知行爱智告诉你机场广告该怎么投放
  9. 【虹科白皮书】高级分析对NetOps的重要性
  10. 108朵玫瑰花的含义