SpingBoot+Quartrz单机版实现动态定时任务(利用反射实现自定义业务)

95 篇文章 3 订阅
29 篇文章 1 订阅
😊 @ 作者: 一恍过去
😊 @ 社区: Java技术栈交流
🎉 @ 主题: SpingBoot+Quartrz单机版实现动态定时任务(利用反射实现自定义业务)
⏱️ @ 创作时间: 2022年06月06日

《SpingBoot+Quartrz集群版实现动态定时任务》

《SpingBoot+Quartrz生产环境的应用支持分布式、自定义corn、反射执行多任务》

1、引入quartz关联pom

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
     <groupId>org.mybatis.spring.boot</groupId>
     <artifactId>mybatis-spring-boot-starter</artifactId>
     <version>2.1.2</version>
</dependency>
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>8.0.20</version>
</dependency>
<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <optional>true</optional>
</dependency>

2、yml配置

只展示quartz相关的配置

spring:
  quartz:
    scheduler-name: quartz-single-scheduler
    properties:
      org:
        quartz:
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            # 线程数量
            threadCount: 10
            # 线程优先级
            threadPriority: 5
            # 线程池中线程名称的前缀
            threadNamePrefix: quartz-single
            # 加载任务代码的ClassLoader是否从外部继承
            threadsInheritContextClassLoaderOfInitializingThread: true

3、建立数据表

此处是单机版本的quartz,没有使用quartz原生的表结构

CREATE TABLE `sys_job` (
  `id` varchar(32) NOT NULL COMMENT '任务ID',
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '任务名称',
  `invoke_target` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '目标字符串',
  `cron_expression` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'cron执行表达式',
  `run_time` timestamp NULL DEFAULT NULL COMMENT '上次执行时间',
  `next_run_time` timestamp NULL DEFAULT NULL COMMENT '下次执行时间',
  `status` int NOT NULL COMMENT '状态:1-执行中,2-暂停',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='定时任务调度表'

4、entity

@Data
public class JobEntity {
    /**
     * id
     */
    private String id;

    /**
     * 任务名
     */
    private String name;


    /**
     * 目标字符串
     * 格式bean.method(params)
     * String字符串类型,包含'、boolean布尔类型,等于true或者false
     * long长整形,包含L、double浮点类型,包含D、其他类型归类为整形
     * aa.aa('String',100L,20.20D)
     */
    private String invokeTarget;

    /**
     * cron表达式
     */
    private String cronExpression;


    /**
     * 执行时间
     */
    private Date runTime;

    /**
     * 下次执行时间
     */
    private Date nextRunTime;

    /**
     * 状态:1-执行中,2-暂停
     */
    private Integer status;
}

5、mapper(接口)

@Mapper
public interface TaskMapper {
    /**
     * 任务列表
     *
     * @return
     */
    List<JobEntity> jobList();

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    JobEntity selectById(String id);

    /**
     * 新增
     *
     * @param job
     * @return
     */
    int insert(JobEntity job);

    /**
     * 更新
     *
     * @param job
     * @return
     */
    int update(JobEntity job);

    /**
     * 删除
     *
     * @param id
     * @return
     */
    int delete(String id);

}

6、mappring(xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.quartz.mapper.TaskMapper">

    <resultMap type="com.example.quartz.entity.JobEntity" id="BaseResultMap">
        <id property="id" column="id" jdbcType="VARCHAR"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="invokeTarget" column="invoke_target" jdbcType="VARCHAR"/>
        <result property="cronExpression" column="cron_expression" jdbcType="VARCHAR"/>
        <result property="runTime" column="run_time" jdbcType="TIMESTAMP"/>
        <result property="nextRunTime" column="next_run_time" jdbcType="TIMESTAMP"/>
        <result property="status" column="status" jdbcType="INTEGER"/>
    </resultMap>

    <sql id="Base_Column_List">
        id,name,invoke_target,cron_expression,run_time,next_run_time,status
    </sql>

    <select id="jobList" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from sys_job where `status` = 0
    </select>

    <select id="selectById" parameterType="string" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from sys_job where id =#{id}
    </select>


    <insert id="insert" parameterType="com.example.quartz.entity.JobEntity">
        insert into sys_job(id, name, invoke_target, cron_expression, run_time, next_run_time, status)
        values (#{id}, #{name}, #{invokeTarget}, #{cronExpression}, #{runTime}, #{nextRunTime}, #{status})
    </insert>

    <update id="update" parameterType="com.example.quartz.entity.JobEntity">
        update sys_job
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="invokeTarget != null">
                invoke_target = #{invokeTarget},
            </if>
            <if test="cronExpression != null">
                cron_expression = #{cronExpression},
            </if>
            <if test="runTime != null">
                run_time = #{runTime},
            </if>
            <if test="nextRunTime != null">
                next_run_time = #{nextRunTime},
            </if>
            <if test="status != null">
                status = #{status},
            </if>
        </set>
        where id = #{id,jdbcType=INTEGER}
    </update>

    <delete id="delete" parameterType="string">
        delete
        from sys_job
        where id = #{id}
    </delete>

</mapper>

7、工具类

import com.example.quartz.entity.JobEntity;
import org.quartz.CronExpression;
import org.quartz.JobDataMap;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class QuartzUtils {

    /**
     * 解析invokeTarget内容
     *
     * @param jobEntity
     * @return
     */
    public static Map<String, Object> generatorJobDataMap(JobEntity jobEntity) {

        String jobId = jobEntity.getId();
        String jobName = jobEntity.getName();
        String cron = jobEntity.getCronExpression();
        /*
         * invokeTarget:格式bean.method(params)
         * String字符串类型,包含'、boolean布尔类型,等于true或者false
         * long长整形,包含L、double浮点类型,包含D、其他类型归类为整形
         */
        String invokeTarget = jobEntity.getInvokeTarget();

        String beanName = invokeTarget.substring(0, invokeTarget.indexOf("."));

        String methodName = invokeTarget.substring(invokeTarget.indexOf(".") + 1, invokeTarget.indexOf("("));


        // 获取参数
        List<Object[]> methodParams = new ArrayList<>();
        // 默认第一个参数 加上 id 参数, 第二个参数未name
        methodParams.add(new Object[]{jobId, String.class});
        methodParams.add(new Object[]{jobName, String.class});

        // 解析参数
        getMethodParams(methodParams, invokeTarget);
        Map<String, Object> map = new HashMap<>();
        map.put("beanName", beanName);
        map.put("methodName", methodName);
        map.put("jobId", jobId);
        map.put("jobName", jobName);
        map.put("cron", cron);
        map.put("methodParams", methodParams);

        return map;
    }


    /**
     * 返回一个布尔值代表一个给定的Cron表达式的有效性
     *
     * @param cronExpression Cron表达式
     */
    public static void isValid(String cronExpression) {
        boolean expression = CronExpression.isValidExpression(cronExpression);
        if (!expression) {
            throw new RuntimeException("cron表达式错误!");
        }
    }


    /**
     * 返回下一个执行时间根据给定的Cron表达式
     *
     * @param cronExpression Cron表达式
     * @param num            获取数量
     * @param format         是否格式化为字符串
     * @return Date 下次Cron表达式执行时间
     */
    public static Object getNextExecution(String cronExpression, int num, boolean format) {

        List<String> list = new ArrayList<>();
        try {
            CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
            cronTriggerImpl.setCronExpression(cronExpression);
            // 近n次时间
            List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, num);
            //不进行格式化
            if (!format) {
                return dates;
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (Date date : dates) {
                list.add(dateFormat.format(date));
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    public static Date nextCurrentTime(String cron) {
        //如果存在获取的新的下次执行时间和当前已执行的时间一致,则返回第二个执行时间
        List<Date> execution = (List<Date>) getNextExecution(cron, 2, false);
        long timeMillis = System.currentTimeMillis();
        if (Math.abs(timeMillis - execution.get(0).getTime()) > 1000) {
            return execution.get(0);
        }
        //因为如果还在当前任务执行时间节点上,获取到的下次时间和当前是一致的,所有要获取下下次的时间节点
        return execution.get(1);
    }

    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    public static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            classs[index] = (Class<?>) os[1];
            index++;
        }
        return classs;
    }

    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    public static Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] objects = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            objects[index] = os[0];
            index++;
        }
        return objects;
    }

    /**
     * 解析表达式中的参数
     *
     * @param invokeTarget
     * @return
     */
    private static void getMethodParams(List<Object[]> methodParams, String invokeTarget) {
        String paramStr = invokeTarget.substring(invokeTarget.indexOf("(") + 1, invokeTarget.indexOf(")"));

        String[] params = paramStr.split(",");

        for (String param : params) {
            String str = param.trim();
            // String字符串类型,包含`'`;
            if (str.contains("'")) {
                methodParams.add(new Object[]{StringUtils.replace(str, "'", ""), String.class});
            }
            // boolean布尔类型,等于true或者false
            else if ("true".equals(str) || "false".equals(str)) {
                methodParams.add(new Object[]{Boolean.valueOf(str), Boolean.class});
            }
            // long长整形,包含L
            else if (str.toUpperCase().contains("L")) {
                methodParams.add(new Object[]{Long.valueOf(StringUtils.replace(str.toUpperCase(), "L", "")), Long.class});
            }
            // double浮点类型,包含D
            else if (str.toUpperCase().contains("D")) {
                methodParams.add(new Object[]{Double.valueOf(StringUtils.replace(str.toUpperCase(), "D", "")), Double.class});
            }
            // 其他类型归类为整形
            else {
                methodParams.add(new Object[]{Integer.valueOf(str), Integer.class});
            }
        }
    }
}

8、BaseQuartzJobBean

BaseQuartzJobBean主要就是根据beanName、methodName、methodParams通过反射执行具体的业务代码;

import com.example.quartz.entity.JobEntity;
import com.example.quartz.mapper.TaskMapper;
import com.example.quartz.utils.QuartzUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class BaseQuartzJobBean extends QuartzJobBean {

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private JobManager jobManager;

    @Resource
    private TaskMapper taskMapper;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        String jobId = jobDetail.getKey().getName();
        log.info("执行任务,任务ID:" + jobId);

        // 获取参数
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        Map<String, Object> paramMap = (Map<String, Object>) jobDataMap.get("paramMap");
        try {
            // 通过反射执行方法
            String invokeTarget = paramMap.get("beanName").toString();
            log.info("beanName:" + invokeTarget);

            String methodStr = paramMap.get("methodName").toString();
            log.info("methodName:" + methodStr);

            // 执行具体类的方法
            List<Object[]> methodParams = (List<Object[]>) paramMap.get("methodParams");
            Object beanName = applicationContext.getBean(invokeTarget);
            Method method = beanName.getClass().getMethod(methodStr, QuartzUtils.getMethodParamsType(methodParams));

            // 执行任务
            method.invoke(beanName, QuartzUtils.getMethodParamsValue(methodParams));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("没有找到可执行方法!");
            // 需要关闭任务
            jobManager.deleteJob(jobId);
        } finally {
            // 更新执行时间
            String cron = paramMap.get("cron").toString();
            Date nextCurrentTime = QuartzUtils.nextCurrentTime(cron);
            JobEntity job = new JobEntity();
            job.setId(jobId);
            job.setRunTime(new Date());
            job.setNextRunTime(nextCurrentTime);
            taskMapper.update(job);
        }
    }
}

9、业务代码执行类

SysServiceJob 为一个业务代码的执行类,类中可以存在多个方法,也可以有多个类,这些都没有限制可以任意定义;具体执行那个类的那个方法由实体中的invokeTarget 参数解析而来,并且通过BaseQuartzJobBean类利用反射机制进行执行;

@Service
@Slf4j
public class SysServiceJob {
    /**
     * 参数由任务中的 invokeTarget 解析而来,参数个数以及类型需要与invokeTarget中的一致
     *
     * @param jobId
     * @param jobName
     * @param str
     * @param l
     * @param d
     * @param b
     */
    public void test(String jobId, String jobName, String str, Long l, Double d, Boolean b) {
        log.info("ID:{},Name:{}", jobId, jobName);
        // 打印参数
        log.info("参数:str={},l={},d={},b={}", str, l, d, b);
    }
}

10、JobManager

JobManager封装了对任务的修改、暂停、恢复、删除、新增等操作处理;

import com.example.quartz.entity.JobEntity;
import com.example.quartz.mapper.TaskMapper;
import com.example.quartz.utils.QuartzUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

@Component
@Slf4j
public class JobManager {

    @Resource
    private Scheduler scheduler;

    @Resource
    private TaskMapper taskMapper;


    /**
     * 开启一个定时任务
     *
     * @param jobEntity 任务实体
     * @throws Exception
     */
    public void startJob(JobEntity jobEntity) {
        try {
            String jobId = jobEntity.getId();
            // 判断是否存在
            JobKey jobKey = JobKey.jobKey(jobId);
            boolean exists = scheduler.checkExists(jobKey);
            if (exists) {
                throw new RuntimeException("任务已经存在!");
            }
            log.info("======== 创建任务:{} ========", jobId);

            // 构建参数
            JobDataMap jobDataMap = new JobDataMap();
            Map<String, Object> map = QuartzUtils.generatorJobDataMap(jobEntity);
            jobDataMap.put("paramMap", map);
            // 以任务的ID来构建定时任务
            Class<? extends Job> aClass = BaseQuartzJobBean.class;
            JobBuilder jobBuilder = JobBuilder.newJob(aClass).withIdentity(jobId);
            jobBuilder.setJobData(jobDataMap);
            JobDetail jobDetail = jobBuilder.build();

            // 设置cron
            String cron = jobEntity.getCronExpression();
            // 验证cron
            QuartzUtils.isValid(cron);
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

            // 任务触发器
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobId).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("任务启动失败!");
        }
    }


    /**
     * 重新执行任务 - 更新任务
     *
     * @param jobEntity 任务实体
     * @throws SchedulerException
     */
    public void updateJob(JobEntity jobEntity) {
        try {
            String jobId = jobEntity.getId();
            log.info("======== 更新任务:{} ========", jobId);
            JobKey jobKey = JobKey.jobKey(jobEntity.getId());
            boolean exists = scheduler.checkExists(jobKey);
            if (!exists) {
                // 任务原有没有执行,则不继续执行
                return;
            }
            log.info("======== 创建任务:{} ========", jobId);

            // 重新构建参数
            Map<String, Object> map = (Map<String, Object>) scheduler.getJobDetail(jobKey).getJobDataMap().get("paramMap");
            map.clear();
            map.putAll(QuartzUtils.generatorJobDataMap(jobEntity));

            // 根据Id获取触发器
            TriggerKey triggerKey = TriggerKey.triggerKey(jobId);
            // 设置cron
            String cron = jobEntity.getCronExpression();
            // 验证cron
            QuartzUtils.isValid(cron);
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
            // 重新构建任务触发器
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            TriggerBuilder<CronTrigger> builder = trigger.getTriggerBuilder().withIdentity(triggerKey);
            trigger = builder.withSchedule(scheduleBuilder).build();

            // 重新执行任务
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new RuntimeException("任务更新失败!");
        }
    }

    /**
     * 删除定时任务
     *
     * @param jobId 定时任务名称
     * @throws SchedulerException
     */
    public void deleteJob(String jobId) {
        try {
            JobKey jobKey = JobKey.jobKey(jobId);
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new RuntimeException("任务删除失败! ");
        }
    }


    /**
     * 暂停任务
     *
     * @param jobId 定时任务ID,与构造任务时的ID一致
     * @throws SchedulerException
     */
    public void pauseJob(String jobId) {
        try {
            JobKey jobKey = JobKey.jobKey(jobId);
            boolean exists = scheduler.checkExists(jobKey);
            if (!exists) {
                throw new RuntimeException("任务未运行!");
            }
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new RuntimeException("任务暂停失败:" + e.getMessage());
        }
    }

    /**
     * 恢复任务
     *
     * @param jobId 定时任务ID,与构造任务时的ID一致
     * @throws SchedulerException
     */
    public void resumeJob(String jobId) {
        // 恢复任务时会立即执行一次任务
        log.info("恢复任务:" + jobId);
        try {
            JobKey jobKey = JobKey.jobKey(jobId);
            boolean exists = scheduler.checkExists(jobKey);

            if (exists) {
                scheduler.resumeJob(jobKey);
            } else {
                // 任务暂未运行
                // 从数据库中查询,并且执行任务
                JobEntity jobEntity = taskMapper.selectById(jobId);
                startJob(jobEntity);
                if (jobEntity == null) {
                    throw new RuntimeException("任务不存在!");
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new RuntimeException("任务恢复失败:" + e.getMessage());
        }
    }

    /**
     * 立即执行一次任务 : 没有达到任务的执行周期直接触发
     *
     * @param jobId 定时任务ID,与构造任务时的ID一致
     * @throws SchedulerException
     */
    public void runOnceJob(String jobId) {
        try {
            JobKey jobKey = JobKey.jobKey(jobId);
            boolean exists = scheduler.checkExists(jobKey);
            if (!exists) {
                throw new RuntimeException("任务未运行!");
            }
            log.info("执行任务:" + jobId);
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new RuntimeException("任务执行失败:" + e.getMessage());
        }
    }

    public Object getTaskInfo(String cronExpression, int num) {
        return QuartzUtils.getNextExecution(cronExpression, num, true);
    }
}

11、TaskController

TaskController测试入口类,此处方便测试没有service层代码

@RequestMapping("/task")
@Slf4j
public class TaskController {

    @Resource
    private JobManager jobManager;

    @Resource
    private TaskMapper taskMapper;

    @ApiOperation(value = "新增任务", notes = "新增任务")
    @ApiOperationSupport(order = 5)
    @PostMapping("/insert")
    public String check(@RequestBody JobEntity job) {
        job.setId(UUIDUtils.getUuId());
        // 插入数据库
        taskMapper.insert(job);
        // 启动任务
        jobManager.startJob(job);
        return "操作成功";
    }

    @ApiOperation(value = "更新任务", notes = "更新任务")
    @ApiOperationSupport(order = 10)
    @PutMapping("/update")
    public String update(@RequestBody JobEntity job) {
        // 更新数据库
        int update = taskMapper.update(job);
        if (update > 0) {
            // 启动任务
            jobManager.updateJob(job);
        }
        return "操作成功";
    }

    @ApiOperation(value = "删除任务", notes = "删除任务")
    @ApiOperationSupport(order = 10)
    @DeleteMapping("/delete/{id}")
    public String delete(@PathVariable String id) {
        // 删除数据库
        taskMapper.delete(id);
        // 启动任务
        jobManager.deleteJob(id);
        return "操作成功";
    }


    @ApiOperation(value = "暂停任务", notes = "暂停任务")
    @ApiOperationSupport(order = 10)
    @PostMapping("/pause/{id}")
    public String pause(@PathVariable String id) {
        // 更新数据库
        JobEntity job = taskMapper.selectById(id);
        job.setStatus(2);
        taskMapper.update(job);
        // 启动任务
        jobManager.pauseJob(id);
        return "操作成功";
    }


    @ApiOperation(value = "恢复任务", notes = "恢复任务")
    @ApiOperationSupport(order = 10)
    @PostMapping("/resume/{id}")
    public String resume(@PathVariable String id) {
        // 更新数据库
        JobEntity job = taskMapper.selectById(id);
        job.setStatus(1);
        taskMapper.update(job);
        // 启动任务
        jobManager.resumeJob(id);
        return "操作成功";
    }

    @ApiOperation(value = "执行一次任务", notes = "执行一次任务")
    @ApiOperationSupport(order = 20)
    @PostMapping("/once/{id}")
    public String runOnceJob(@PathVariable String id) {
        jobManager.runOnceJob(id);
        return "操作成功";
    }

    /**
     * 查询详情
     *
     * @param id
     * @return
     */
    @GetMapping("info/{id}")
    @ApiOperation(value = "查询执行时间", notes = "查询执行时间")
    @ApiImplicitParam(name = "id", value = "任务id", paramType = "path", required = true, dataType = "String")
    public Object getTaskInfo(@PathVariable("id") String id) {
        // 查询数据库
        JobEntity entity = taskMapper.selectById(id);
        return jobManager.getTaskInfo(entity.getCronExpression(), 5);
    }
}

12、测试

此处使用knife4j进行测试,也可以结合postmant或者前端页面进行测试,新增测试如下:

在请求参数中的invokeTarget属性包含了具体需要执行的bean名称、方法名称、参数,内容为:sysServiceJob.test('aaa',10L,20.22D,false),刚好与代码中SysServiceJob类的test方法对应;

在这里插入图片描述

执行效果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一恍过去

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值