玩转 Spring Boot 集成篇(任务动态管理代码篇)

在日常项目研发中,定时任务可谓是必不可少的一环,如果面对任务执行周期固定,业务简单的场景,可直接使用 Spring Boot 内置注解方式实现任务;而如果考虑更为复杂的管理任务信息,在可以通过集成 Quartz 等开源轮子来助力业务研发。

本次主要分享一下 Spring Boot 集成 Quartz 任务框架后,如何实现任务的动态管理,更能够让研发人员专注业务任务的研发,那么就要逐一解决如下疑问。

疑问:是否可以通过 API 动态创建任务呢?

疑问:是否可以通过 API 编辑任务的执行时间呢?

疑问:是否可以通过 API 暂停/恢复任务呢?

疑问:是否可以通过 API 删除任务呢?

疑问:是否可以通过页面完成任务的 CRUD 呢?

考虑到下面的操作是一个大工程,为了方便,重新开启一个 Spring Boot 项目,为了进一步熟练使用 Spring Boot 相关各种 starter,本次选用 MyBatis 作为持久层框架。

421ba338285229eb712957ca9607f4ba.png

1. 核心管理代码

1.1 任务控制器

定义 TaskController,提供用户操作任务的相关 API,例如查询任务列表、添加任务、暂停任务、恢复任务、删除任务。

package com.example.demo.quartz.controller;


import com.example.demo.quartz.common.Result;
import com.example.demo.quartz.service.TaskInfoService;
import com.example.demo.quartz.vo.TaskInfoReq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * 定时任务管理
 **/
@RestController
@RequestMapping("/task")
public class TaskController {


    @Autowired
    private TaskInfoService taskInfoService;


    /**定时器列表*/
    @PostMapping("/list")
    public Result list(@RequestBody TaskInfoReq reqVo) {
        return taskInfoService.selectTaskListByPage(reqVo);
    }


    /**定时器修改*/
    @PostMapping("/edit")
    public Result edit(@RequestBody TaskInfoReq reqVo) {
        return taskInfoService.updateJob(reqVo);
    }


    /**暂停任务*/
    @PostMapping("/pause")
    public Result pause(Integer taskId) {
        return taskInfoService.pauseJob(taskId);
    }


    /**增加任务*/
    @PostMapping("/add")
    public Result add(@RequestBody TaskInfoReq taskInfoReq) {
        return taskInfoService.addJob(taskInfoReq);
    }


    /**恢复任务*/
    @PostMapping("/resume")
    public Result resume(Integer taskId) {
        return taskInfoService.resumeJob(taskId);
    }


    /**删除任务*/
    @PostMapping("/del")
    public Result delete(@RequestBody TaskInfoReq reqVo) {
        return taskInfoService.delete(reqVo);
    }
}

1.2 任务管理

TaskManager 任务管理器,主要接收业务指令,来完成对 Quartz 容器进行操作。

package com.example.demo.quartz.task;


import com.example.demo.quartz.entity.TaskInfo;
import com.example.demo.quartz.utils.SpringContextUtils;
import com.example.demo.quartz.vo.TaskInfoReq;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * 任务管理
 * 1、添加任务 2、更新任务 3、暂停任务 4、恢复任务
 **/
@Component
public class TaskManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(TaskManager.class);
    public static final String JOB_DEFAULT_GROUP_NAME = "JOB_DEFAULT_GROUP_NAME";
    public static final String TRIGGER_DEFAULT_GROUP_NAME = "TRIGGER_DEFAULT_GROUP_NAME";


    @Autowired
    private Scheduler scheduler;
    @Autowired
    private SpringContextUtils springContextUtils;


    /**
     * 添加任务
     */
    public boolean addJob(TaskInfoReq taskInfoReq) {
        boolean flag = true;
        if (!CronExpression.isValidExpression(taskInfoReq.getCron())) {
            LOGGER.error("定时任务表达式有误:{}", taskInfoReq.getCron());
            return false;
        }
        try {
            String className = springContextUtils.getBean(taskInfoReq.getJobName()).getClass().getName();
            JobDetail jobDetail = JobBuilder.newJob().withIdentity(new JobKey(taskInfoReq.getJobName(), JOB_DEFAULT_GROUP_NAME))
                    .ofType((Class<Job>) Class.forName(className))
                    .build();
            Trigger trigger = TriggerBuilder.newTrigger()
                    .forJob(jobDetail)
                    .withSchedule(CronScheduleBuilder.cronSchedule(taskInfoReq.getCron()))
                    .withIdentity(new TriggerKey(taskInfoReq.getJobName(), TRIGGER_DEFAULT_GROUP_NAME))
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
        } catch (Exception e) {
            LOGGER.error("添加定时任务异常:{}", e.getMessage(), e);
            flag = false;
        }
        return flag;
    }


    /**
     * 更新任务
     */
    public boolean updateJob(TaskInfo taskInfo) {
        boolean flag = true;
        try {
            JobKey jobKey = new JobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME);
            TriggerKey triggerKey = new TriggerKey(taskInfo.getJobName(), TRIGGER_DEFAULT_GROUP_NAME);
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
                Trigger newTrigger = TriggerBuilder.newTrigger()
                        .forJob(jobDetail)
                        .withSchedule(CronScheduleBuilder.cronSchedule(taskInfo.getCron()))
                        .withIdentity(triggerKey)
                        .build();
                scheduler.rescheduleJob(triggerKey, newTrigger);
            } else {
                LOGGER.info("更新任务失败,任务不存在,任务名称:{},表达式:{}", taskInfo.getJobName(), taskInfo.getCron());
            }
            LOGGER.info("更新任务成功,任务名称:{},表达式:{}", taskInfo.getJobName(), taskInfo.getCron());
        } catch (SchedulerException e) {
            LOGGER.error("更新定时任务失败:{}", e.getMessage(), e);
            flag = false;
        }
        return flag;
    }


    /**
     * 暂停任务
     */
    public boolean pauseJob(TaskInfo taskInfo) {
        try {
            scheduler.pauseJob(JobKey.jobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME));
            LOGGER.info("任务暂停成功:{}", taskInfo.getId());
            return true;
        } catch (SchedulerException e) {
            LOGGER.error("暂停定时任务失败:{}", e.getMessage(), e);
            return false;
        }
    }


    /**
     * 恢复任务
     */
    public boolean resumeJob(TaskInfo taskInfo) {
        try {
            scheduler.resumeJob(JobKey.jobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME));
            LOGGER.info("任务恢复成功:{}", taskInfo.getId());
            return true;
        } catch (SchedulerException e) {
            LOGGER.error("恢复定时任务失败:{}", e.getMessage(), e);
            return false;
        }
    }
}

1.3 启动管理

1.3.1 QuartzManager

Spring Boot 容器启动时,加载启动所有任务。

package com.example.demo.quartz.config;


import com.example.demo.quartz.common.EnumTaskEnable;
import com.example.demo.quartz.entity.TaskInfo;
import com.example.demo.quartz.service.TaskInfoService;
import com.example.demo.quartz.vo.TaskInfoReq;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Comp
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值