1. 程式人生 > >崛起於Springboot2.0.X之頁面統一操作Quartz所有定時任務何時啟動(47)

崛起於Springboot2.0.X之頁面統一操作Quartz所有定時任務何時啟動(47)

    (記得來開源中國關注我喲!如果部落格被我發現有不好的地方,都會優化更新的,所以關注我呦,嘻嘻)

      技術棧:Springboot2.0.X(2.1.X也可以)+ Quartz +FastMybatis (自認為比mybatis-plus更方便的框架) + Hutool + lombok 

      FastMybatis框架部落格:

                01、

崛起於Springboot2.0.X之入門FastMybatis--> my.oschina.net/mdxlcj/blog/1835665 

                02、崛起於Springboot2.0.X之整合FastMybatis精裝版 --> my.oschina.net/mdxlcj/blog/3059687

                03、

FastMybatis框架快速入門 --> 官方文件

      Quartz入門級框架部落格:

                04、崛起於Springboot2.0.X之整合Quartz定時排程 --> my.oschina.net/mdxlcj/blog/1862472

      序言:之前公司有一個需求說是可以通過一個介面來操作定時任務的時間、包括修改、啟動、關閉等功能,而不是在程式碼中寫死,那個時候從網上找了很久都沒有找到,部落格都特別初級,只能算是入門的後來就不了了之了,目前已經實現開發出這套功能,公開一下,我也希望能夠幫助更多的人在企業更加快速的實現該功能,如圖:

       然後我們看一下,新增定時任務配置截圖:

    這個功能也有批量暫停定時任務的功能、立即恢復、以及執行,當然還有定時任務啟動時的日誌記錄,如圖:

    所以接下來就進入開發階段,由於前端頁面是用vue寫的,我就不把前端程式碼弄出來了,反而這樣會讓大家使用起來比較費力,所以我們就不用vue進行測試了,只用後段自己生成資料來測試就可以了,也能夠達到目的的。

1、pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>4.6.1</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
    <groupId>net.oschina.durcframework</groupId>
    <artifactId>fastmybatis-spring-boot-starter</artifactId>
    <version>1.8.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

2、application.properties

mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ss?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

3、mysql表結構

CREATE TABLE `schedule_job` (
  `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任務id',
  `bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名稱',
  `method_name` varchar(100) DEFAULT NULL COMMENT '方法名',
  `params` varchar(2000) DEFAULT NULL COMMENT '引數',
  `cron_expression` varchar(100) DEFAULT NULL COMMENT 'cron表示式',
  `status` tinyint(4) DEFAULT NULL COMMENT '任務狀態 0:啟動 1:擱置', 
  `remark` varchar(255) DEFAULT NULL COMMENT '備註',
  `create_time` datetime DEFAULT NULL COMMENT '建立時間',
  PRIMARY KEY (`job_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='定時任務'


CREATE TABLE `schedule_job_log` (
  `log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任務日誌id',
  `job_id` bigint(20) NOT NULL COMMENT '任務id',
  `bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名稱',
  `method_name` varchar(100) DEFAULT NULL COMMENT '方法名',
  `params` varchar(2000) DEFAULT NULL COMMENT '引數',
  `status` tinyint(4) NOT NULL COMMENT '任務狀態    0:成功    1:失敗',
  `error` varchar(2000) DEFAULT NULL COMMENT '失敗資訊',
  `times` int(11) NOT NULL COMMENT '耗時(單位:毫秒)',
  `create_time` datetime DEFAULT NULL COMMENT '建立時間',
  PRIMARY KEY (`log_id`),
  KEY `job_id` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='定時任務日誌'

4、實體類

import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Data
@Table(name = "schedule_job")
public class ScheduleJobEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY"; //任務排程引數key
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "job_id")
    private Long jobId;            //任務id
    @Column(name = "bean_name")
    private String beanName;       //spring bean名稱
    @Column(name = "method_name")
    private String methodName;     //方法名
    @Column(name = "params")
    private String params;         //引數
    @Column(name = "cron_expression")
    private String cronExpression; //cron表示式
    @Column(name = "status")
    private Integer status;        //任務狀態
    @Column(name = "remark")
    private String remark;         //備註
    @Column(name = "create_time")
    private Date createTime;       //建立時間
}
import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

/**
 * 定時執行日誌
 */
@Data
@Table(name = "schedule_job_log")
public class ScheduleJobLogEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "log_id")
    private Long logId;       //日誌id
    @Column(name = "job_id")
    private Long jobId;       //任務id
    @Column(name = "bean_name")
    private String beanName;  //spring bean名稱
    @Column(name = "method_name")
    private String methodName;//方法名
    @Column(name = "params")
    private String params;    //引數
    @Column(name = "status")
    private Integer status;   // 任務狀態    0:成功    1:失敗
    @Column(name = "error")
    private String error;     //失敗資訊
    @Column(name = "times")
    private Integer times;    //耗時(單位:毫秒)
    @Column(name = "create_time")
    private Date createTime;  //建立時間
}

    請求介面統一返回實體類

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
@Data
@AllArgsConstructor
@ToString
public class ResultData {
    private boolean success;
    private String code;
    private String message;
    private Object data;

    public ResultData() {
        this.success = true;
        this.code = "200";
    }
}

5、Util層

        這一層程式碼大家看不明白沒有關係,畢竟這些都是工具類裡面的,不是我們開發日常編碼那種,所以只需要配置一次就好啦,正常開發我們就直接跳過第五步就好了。

import org.apache.commons.lang.StringUtils;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class ScheduleJob extends QuartzJobBean {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private ExecutorService service = Executors.newSingleThreadExecutor();

    @Override
    protected void executeInternal(JobExecutionContext context) {
        ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap()
                .get(ScheduleJobEntity.JOB_PARAM_KEY);

        //獲取spring bean
        ScheduleJobService scheduleJobService = (ScheduleJobService) SpringContextUtils.getBean("scheduleJobService");

        //資料庫儲存執行記錄
        ScheduleJobLogEntity log = new ScheduleJobLogEntity();
        log.setJobId(scheduleJob.getJobId());
        log.setBeanName(scheduleJob.getBeanName());
        log.setMethodName(scheduleJob.getMethodName());
        log.setParams(scheduleJob.getParams());
        log.setCreateTime(new Date());

        //任務開始時間
        long startTime = System.currentTimeMillis();

        try {
            //執行任務
            logger.info("任務準備執行,任務ID:" + scheduleJob.getJobId());
            ScheduleRunnable task = new ScheduleRunnable(scheduleJob.getBeanName(),
                    scheduleJob.getMethodName(), scheduleJob.getParams());
            Future<?> future = service.submit(task);

            future.get();

            //任務執行總時長
            long times = System.currentTimeMillis() - startTime;
            log.setTimes((int) times);
            //任務狀態    0:成功    1:失敗
            log.setStatus(0);

            logger.info("任務執行完畢,任務ID:" + scheduleJob.getJobId() + "  總共耗時:" + times + "毫秒");
        } catch (Exception e) {
            logger.error("任務執行失敗,任務ID:" + scheduleJob.getJobId(), e);

            //任務執行總時長
            long times = System.currentTimeMillis() - startTime;
            log.setTimes((int) times);

            //任務狀態    0:成功    1:失敗
            log.setStatus(1);
            log.setError(StringUtils.substring(e.toString(), 0, 2000));
        } finally {
            scheduleJobService.saveLog(log);
        }
    }
}
import org.apache.commons.lang.StringUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;

public class ScheduleRunnable implements Runnable {
    private Object target;
    private Method method;
    private String params;

    public ScheduleRunnable(String beanName, String methodName, String params) throws NoSuchMethodException, SecurityException {
        this.target = SpringContextUtils.getBean(beanName);
        this.params = params;

        if (StringUtils.isNotBlank(params)) {
            this.method = target.getClass().getDeclaredMethod(methodName, String.class);
        } else {
            this.method = target.getClass().getDeclaredMethod(methodName);
        }
    }

    @Override
    public void run() {
        try {
            ReflectionUtils.makeAccessible(method);
            if (StringUtils.isNotBlank(params)) {
                method.invoke(target, params);
            } else {
                method.invoke(target);
            }
        } catch (Exception e) {
            throw new RuntimeException("執行定時任務失敗", e);
        }
    }
}
import org.quartz.*;

public class ScheduleUtils {
    private final static String JOB_NAME = "TASK_";

    /**
     * 獲取觸發器key
     */
    public static TriggerKey getTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(JOB_NAME + jobId);
    }

    /**
     * 獲取jobKey
     */
    public static JobKey getJobKey(Long jobId) {
        return JobKey.jobKey(JOB_NAME + jobId);
    }

    /**
     * 獲取表示式觸發器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("獲取定時任務CronTrigger出現異常", e);
        }
    }

    /**
     * 建立定時任務
     */
    public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            //構建job資訊
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getJobId())).build();

            //表示式排程構建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();

            //按新的cronExpression表示式構建一個新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder).build();

            //放入引數,執行時的方法可以獲取
            jobDetail.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);

            scheduler.scheduleJob(jobDetail, trigger);

            //暫停任務
            if (scheduleJob.getStatus() == 1) {
                pauseJob(scheduler, scheduleJob.getJobId());
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("建立定時任務失敗", e);
        }
    }

    /**
     * 更新定時任務
     */
    public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());

            //表示式排程構建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();

            CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());

            //按新的cronExpression表示式重新構建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            //引數
            trigger.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);

            scheduler.rescheduleJob(triggerKey, trigger);

            //暫停任務
            if (scheduleJob.getStatus() == 1) {
                pauseJob(scheduler, scheduleJob.getJobId());
            }

        } catch (SchedulerException e) {
            throw new RuntimeException("更新定時任務失敗", e);
        }
    }

    /**
     * 立即執行任務
     */
    public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            //引數
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);

            scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
        } catch (SchedulerException e) {
            throw new RuntimeException("立即執行定時任務失敗", e);
        }
    }

    /**
     * 暫停任務
     */
    public static void pauseJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("暫停定時任務失敗", e);
        }
    }

    /**
     * 恢復任務
     */
    public static void resumeJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("暫停定時任務失敗", e);
        }
    }

    /**
     * 刪除定時任務
     */
    public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("刪除定時任務失敗", e);
        }
    }
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextUtils implements ApplicationContextAware {
    public static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        SpringContextUtils.applicationContext = applicationContext;
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static <T> T getBean(String name, Class<T> requiredType) {
        return applicationContext.getBean(name, requiredType);
    }

    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    public static Class<? extends Object> getType(String name) {
        return applicationContext.getType(name);
    }

    /**
     * 從靜態變數applicationContext中取得Bean, 自動轉型為所賦值物件的型別.
     */
    public static <T> T getBean(Class<T> requiredType) {
        return applicationContext.getBean(requiredType);
    }
}
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;


public class ValidatorUtils {
    private static Validator validator;

    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    /**
     * 校驗物件
     *
     * @param object 待校驗物件
     * @param groups 待校驗的組
     * @throws BusinessException 校驗不通過,則報BusinessException異常
     */
    public static void validateEntity(Object object, Class<?>... groups)
            throws RuntimeException {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
            ConstraintViolation<Object> constraint = (ConstraintViolation<Object>) constraintViolations.iterator().next();
            throw new RuntimeException(constraint.getMessage());
        }
    }
}

6、dao層

import com.gitee.fastmybatis.core.mapper.CrudMapper;
import java.util.List;
import java.util.Map;

public interface ScheduleJobDao extends CrudMapper<ScheduleJobEntity,Integer> {
    int updateBatchStatus(Map<String, Object> map);
    List<ScheduleJobEntity> queryList(Map<String, Object> map);
    ScheduleJobEntity queryObject(Long jobId);
    int queryTotal(Map<String, Object> map);
    void deleteBatch(Long[] jobIds);
}
import com.gitee.fastmybatis.core.mapper.CrudMapper;

public interface ScheduleJobLogDao extends CrudMapper<ScheduleJobLogEntity,Long> {
    ScheduleJobLogEntity queryObject(Long jobId);
}

7、Service層

    介面

public interface ScheduleJobService {

    /**
     * 根據ID,查詢定時任務
     */
    ScheduleJobEntity queryObject(Long jobId);

    /**
     * 查詢定時任務列表
     */
    List<ScheduleJobEntity> queryList(Map<String, Object> map);

    /**
     * 查詢總數
     */
    int queryTotal(Map<String, Object> map);

    /**
     * 儲存定時任務
     */
    void save(ScheduleJobEntity scheduleJob);

    /**
     * 更新定時任務
     */
    void update(ScheduleJobEntity scheduleJob);

    /**
     * 批量刪除定時任務
     */
    void deleteBatch(Long[] jobIds);

    /**
     * 批量更新定時任務狀態
     */
    int updateBatch(Long[] jobIds, int status);

    /**
     * 立即執行
     */
    void run(Long[] jobIds);

    /**
     * 暫停執行
     */
    void pause(Long[] jobIds);

    /**
     * 恢復執行
     */
    void resume(Long[] jobIds);

    /**
     * 定時任務列表+總數
     */
    ResultData listJob(int pageIndex, int pageSize);

    /**
     * 日誌查詢
     */
    ResultData queryLogObject(Long jobId);

    /**
     * 儲存日誌記錄
     */
    void saveLog(ScheduleJobLogEntity log);

    /**
     * 查詢日誌記錄列表
     */
    ResultData listLog(int pageIndex, int pageSize);
}

    實現類

import com.gitee.fastmybatis.core.query.Query;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService {
   @Autowired
    private Scheduler scheduler;

   @Autowired
   private ScheduleJobDao schedulerJobDao;

   @Autowired
   ScheduleJobLogDao jobLogDao;
   
   /**
    * 專案啟動時,初始化定時器
    */
   @PostConstruct
   public void init(){
      List<ScheduleJobEntity> scheduleJobList = schedulerJobDao.queryList(new HashMap<>());
      for(ScheduleJobEntity scheduleJob : scheduleJobList){
         CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
            //如果不存在,則建立
            if(cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            }else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
      }
   }
   
   @Override
   public ScheduleJobEntity queryObject(Long jobId) {
      return schedulerJobDao.queryObject(jobId);
   }

   @Override
   public List<ScheduleJobEntity> queryList(Map<String, Object> map) {
      return schedulerJobDao.queryList(map);
   }

   @Override
   public int queryTotal(Map<String, Object> map) {
      return schedulerJobDao.queryTotal(map);
   }


   @Override
   @Transactional
   public void save(ScheduleJobEntity scheduleJob) {
      schedulerJobDao.save(scheduleJob);
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
    }
   
   @Override
   @Transactional
   public void update(ScheduleJobEntity scheduleJob) {
        ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        schedulerJobDao.update(scheduleJob);
    }

   @Override
   @Transactional
    public void deleteBatch(Long[] jobIds) {
       for(Long jobId : jobIds){
          ScheduleUtils.deleteScheduleJob(scheduler, jobId);
       }
       //刪除資料
       schedulerJobDao.deleteBatch(jobIds);
   }

   @Override
    public int updateBatch(Long[] jobIds, int status){
       Map<String, Object> map = new HashMap<>();
       map.put("list", jobIds);
       map.put("status", status);
       return schedulerJobDao.updateBatchStatus(map);
    }
    
   @Override
   @Transactional
    public void run(Long[] jobIds) {
       for(Long jobId : jobIds){
          ScheduleUtils.run(scheduler, queryObject(jobId));
       }
    }

   @Override
   @Transactional
    public void pause(Long[] jobIds) {
        for(Long jobId : jobIds){
          ScheduleUtils.pauseJob(scheduler, jobId);
       }
       updateBatch(jobIds, 1);
    }

   @Override
   @Transactional
    public void resume(Long[] jobIds) {
       for(Long jobId : jobIds){
          ScheduleUtils.resumeJob(scheduler, jobId);
       }
       updateBatch(jobIds, 0);
    }

   @Override
   public ResultData listJob(int pageIndex, int pageSize) {
      ResultData resultData = new ResultData();
      //查詢列表資料
      Query query = new Query();
      query.page(1,10);

      List<ScheduleJobEntity> jobList = schedulerJobDao.list(query);

      long total = schedulerJobDao.getCount(query);

      Map<String,Object> map = new HashMap<>();
      map.put("total",total);
      map.put("list",jobList);

      resultData.setData(map);
      return resultData;
   }

   @Override
   public ResultData queryLogObject(Long jobId) {
      ResultData resultData = new ResultData();
      resultData.setData(jobLogDao.getById(jobId));
      return resultData;
   }

   @Override
   public void saveLog(ScheduleJobLogEntity log) {
      jobLogDao.save(log);
   }

   @Override
   public ResultData listLog(int pageIndex, int pageSize) {
      ResultData resultData = new ResultData();

      //查詢列表資料
      Query query = new Query();
      query.page(pageIndex,pageSize);

      List<ScheduleJobLogEntity> jobList = jobLogDao.list(query);

      long total = jobLogDao.getCount(query);

      Map<String,Object> map = new HashMap<>();
      map.put("total",total);
      map.put("list",jobList);

      resultData.setData(map);

      return resultData;
   }
}

8、Controller層

@RestController
@RequestMapping("/schedule")
public class ScheduleJobController {

    @Autowired
    private ScheduleJobService scheduleJobService;

    /**
     * 定時任務列表
     */
    @RequestMapping("/list")
    public ResultData list() {
        return scheduleJobService.listJob(1,10);
    }

    /**
     * 定時任務資訊
     */
    @RequestMapping("/info/{jobId}")
    public ResultData info(@PathVariable("jobId") Long jobId) {
        ScheduleJobEntity schedule = scheduleJobService.queryObject(jobId);
        ResultData resultData = new ResultData();
        resultData.setData(schedule);

        return resultData;

    }

    /**
     * 儲存定時任務 @RequestBody ScheduleJobEntity scheduleJob
     */
    @RequestMapping("/save")
    public ResultData save() {

        //先測試編寫一個臨時ScheduleJobEntity,畢竟後端頁面不會寫
        ScheduleJobEntity jobEntity = createJob();
        ValidatorUtils.validateEntity(jobEntity);

        scheduleJobService.save(jobEntity);

        return new ResultData();
    }

    /**
     * 修改定時任務
     */
    @RequestMapping("/update")
    public ResultData update(@RequestBody ScheduleJobEntity scheduleJob) {
        ValidatorUtils.validateEntity(scheduleJob);

        scheduleJobService.update(scheduleJob);
        return new ResultData();
    }

    /**
     * 刪除定時任務
     */
    @RequestMapping("/delete")
    public ResultData delete(@RequestBody Long[] jobIds) {
        scheduleJobService.deleteBatch(jobIds);
        return new ResultData();
    }

    /**
     * 立即執行任務
     */
    @RequestMapping("/run")
    public ResultData run(@RequestBody Long[] jobIds) {
        scheduleJobService.run(jobIds);
        return new ResultData();
    }

    /**
     * 暫停定時任務
     */
    @RequestMapping("/pause")
    public ResultData pause(@RequestBody Long[] jobIds) {
        scheduleJobService.pause(jobIds);
        return new ResultData();
    }

    /**
     * 恢復定時任務
     */
    @RequestMapping("/resume")
    public ResultData resume(@RequestBody Long[] jobIds) {
        scheduleJobService.resume(jobIds);
        return new ResultData();
    }

    /**
     * 定時任務日誌列表
     */
    @RequestMapping("/log/list")
    public ResultData listLog() {
       return scheduleJobService.listLog(1,10);
    }

    /**
     * 定時任務日誌資訊查詢
     */
    @RequestMapping("/log/info/{logId}")
    public ResultData infoLog(@PathVariable("logId") Long logId) {
        return scheduleJobService.queryLogObject(logId);
    }

    public static ScheduleJobEntity createJob(){
        ScheduleJobEntity jobEntity = new ScheduleJobEntity();
        jobEntity.setBeanName("mytask");
        jobEntity.setCreateTime(new Date());
        jobEntity.setMethodName("firstTask");
        jobEntity.setCronExpression("0/10 * * * * ?");
        jobEntity.setParams(null);
        jobEntity.setStatus(1);
        jobEntity.setRemark("測試該定時任務的執行");
        return jobEntity;
    }
}

9、定時任務

        該類涉及到@Component(value = "mytask")和方法名都將被前端頁面使用,使用這兩個屬性值定位到何時執行該定時任務。

import org.springframework.stereotype.Component;

/**
 * @Author:MuJiuTian
 * @Description: 頁面控制定時任務的觸發時間、開啟和關閉都要有定時任務
 * @Date: Created in 下午2:06 2019/8/27
 */
@Component(value = "mytask")
public class MyTask {

    public void firstTask(){
        //再這個方法中執行task業務邏輯
        System.out.println("該定時任務由前臺頁面控制何時啟動");
    }
}

10、啟動測試

        謹記,啟動類,千萬不要新增@MapperScan(),因為集成了FastMybatis框架,已經自動封裝了。如果大家不喜歡這個框架的話,也可以使用Mybatis或者流行的Mybatis-plus或者TKMybatis、EasyMybatis等等框架。

        測試介面:http://localhost:8081/schedule/save,我的埠是8081的。

         結果如圖已經觸發我們剛剛寫的定時任務了:

     成功啦!不喜歡用FastMybatis的話用其他框架操作mysql吧,畢竟我不太喜歡用mybatis-plus,畢竟需要多寫程式碼。     &nbs