SpringBoot如何实现定时任务(下)

电子说

1.3w人已加入

描述

2.6 定时任务管理实现类

@Slf4j
 @Service
 public class ScheduledTaskServiceImpl implements ScheduledTaskService {
 
     /**
      * 可重入锁
      */
    private ReentrantLock lock = new ReentrantLock();
 
     /**
      * 定时任务线程池
      */
     @Autowired
     private ThreadPoolTaskScheduler threadPoolTaskScheduler;
 
     /**
      * 启动状态的定时任务集合
      */
     public Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();
 
     @Autowired
     private ScheduledJobService scheduledJobService;
 
     @Override
     public Boolean start(ScheduledJob scheduledJob) {
         String jobKey = scheduledJob.getJobKey();
         log.info("启动定时任务"+jobKey);
         //添加锁放一个线程启动,防止多人启动多次
         lock.lock();
         log.info("加锁完成");
 
         try {
             if(this.isStart(jobKey)){
                 log.info("当前任务在启动状态中");
                 return false;
             }
             //任务启动
             this.doStartTask(scheduledJob);
         } finally {
             lock.unlock();
             log.info("解锁完毕");
         }
 
         return true;
     }
 
     /**
      * 任务是否已经启动
      */
     private Boolean isStart(String taskKey) {
         //校验是否已经启动
         if (scheduledFutureMap.containsKey(taskKey)) {
             if (!scheduledFutureMap.get(taskKey).isCancelled()) {
                 return true;
             }
         }
         return false;
     }
 
     @Override
     public Boolean stop(String jobKey) {
         log.info("停止任务 "+jobKey);
         boolean flag = scheduledFutureMap.containsKey(jobKey);
         log.info("当前实例是否存在 "+flag);
         if(flag){
             ScheduledFuture scheduledFuture = scheduledFutureMap.get(jobKey);
 
             scheduledFuture.cancel(true);
 
             scheduledFutureMap.remove(jobKey);
         }
         return flag;
     }
 
     @Override
     public Boolean restart(ScheduledJob scheduledJob) {
         log.info("重启定时任务"+scheduledJob.getJobKey());
         //停止
         this.stop(scheduledJob.getJobKey());
 
         return this.start(scheduledJob);
     }
 
     /**
      * 执行启动任务
      */
     public void doStartTask(ScheduledJob sj){
         log.info(sj.getJobKey());
         if(sj.getStatus().intValue() != 1)
             return;
         Class? clazz;
         ScheduledOfTask task;
         try {
             clazz = Class.forName(sj.getJobKey());
             task = (ScheduledOfTask) SpringContextUtil.getBean(clazz);
         } catch (ClassNotFoundException e) {
             throw new IllegalArgumentException("spring_scheduled_cron表数据" + sj.getJobKey() + "有误", e);
         }
         Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类必须实现ScheduledOfTask接口");
         ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(task,(triggerContext -> new CronTrigger(sj.getCronExpression()).nextExecutionTime(triggerContext)));
         scheduledFutureMap.put(sj.getJobKey(),scheduledFuture);
     }
 
     @Override
     public void initTask() {
         List

2.8 上面用到的获取Bean的工具类SpringContextUtil

@Component
 public class SpringContextUtil implements ApplicationContextAware {
 
 
     private static ApplicationContext applicationContext = null;
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         if(SpringContextUtil.applicationContext == null){
             SpringContextUtil.applicationContext  = applicationContext;
         }
     }
 
     public static ApplicationContext getApplicationContext() {
         return applicationContext;
     }
 
     public static Object getBean(String name){
         return getApplicationContext().getBean(name);
     }
 
     public static

2.9 表操作对应的一些类

Pojo

@Data
 @TableName("scheduled_job")
 public class ScheduledJob {
 
     @TableId(value = "job_id",type = IdType.AUTO)
     private Integer jobId;
 
     private String jobKey;
 
     private String cronExpression;
 
     private String taskExplain;
 
     private Integer status;
 
 }

ScheduledJobMapper

public interface ScheduledJobMapper extends BaseMapper<ScheduledJob> {
 }

ScheduledJobService

public interface ScheduledJobService extends IService<ScheduledJob> {
 
     /**
      * 修改定时任务,并重新启动
      * @param scheduledJob
      * @return
      */
     boolean updateOne(ScheduledJob scheduledJob);
 }
@Service
 @Slf4j
 public class ScheduledJobServiceImpl extends ServiceImpl

2.10 修改定时任务的接口

@RestController
 @RequestMapping("/job")
 public class ScheduledJobController {
 
     @Autowired
     private ScheduledJobService scheduledJobService;
 
     @PostMapping(value = "/update")
     public CallBackResult update(HttpServletRequest request, ScheduledJob scheduledJob){
          if(scheduledJobService.updateOne(scheduledJob))
              return new CallBackResult(true,"修改成功");
          return new CallBackResult(false,"修改失败");
     }
 
 }

3、测试结果

3.1 启动项目,看下定时任务的执行结果,控制台输出结果

代码

我们可以看到任务1是每5秒执行一次,任务2是12秒执行一次

3.2 修改任务1的cron参数或者状态

3.2.1 修改cron,执行周期改为20秒执行一次,状态不变

代码

代码

代码

再看控制台输出结果,任务2没变化,任务1由5秒一次变成了20秒一次了

代码

3.2.1 修改状态

再看控制台输出结果,任务2没变化,任务1已经不再执行了

代码

最后

第二种方式支持通过接口的方式去改动,并且不需要重启,当然啦,也可以直接在数据库中添加或修改数据后重启项目,配置更加灵活一点。

如果是一个固定的需求,执行周期一定不会变的了,推荐还是第一种写法,毕竟简单嘛。

如果觉得写得还不错的话,给个推荐鼓励一下吧。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分