java之动态配置定时任务

需求场景

最近我在工作当中遇到需要支持用户在前端界面上动态配置定时任务的执行时间和执行参数的需求。在我们平时的开发当中,传统的方式就是在类的方法上使用注解@Scheduled(cron = “0 0 0 1 * ?”)这样来配置时任务,但是不能够满足我们的需求,不能动态配置和改变任务的执行时间和执行参数。我们需要怎么做?接下来我们来实现一下

上才艺

目录结构

在这里插入图片描述

DemoApplication

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

TaskController

package com.example.demo.controller;

import com.example.demo.service.TaskService;
import com.example.demo.task.ScheduleTask;
import com.example.demo.utils.ScheduleUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 控制器
 *
 * @author zhongxiaojian
 * @date 2020/8/14
 **/
@RestController
@RequestMapping("task")
public class TaskController {

    @Autowired
    private TaskService service;

    /**
     * 新增或者修改
     *
     * @param id      任务ID
     * @param cron    执行时间表达式
     * @param keyword 关键字参数
     * @return true or false
     */
    @PostMapping("saveOrEdit")
    public boolean saveOrEdit(@RequestParam("id") String id,
                              @RequestParam("cron") String cron,
                              @RequestParam("keyword") String keyword) {
        return ScheduleUtil.reset(new ScheduleTask(id, service, keyword), cron);
    }
}

TaskService & TaskServiceImpl

package com.example.demo.service;

/**
 * 任务处理
 *
 * @author zhongxiaojian
 * @date 2020/8/14
 **/
public interface TaskService {

    /**
     * 业务处理
     *
     * @param keyword 关键参数
     */
    void work(String keyword);
}
package com.example.demo.service.impl;

import com.example.demo.service.TaskService;
import org.springframework.stereotype.Service;

/**
 * @author zhongxiaojian
 * @date 2020/8/14
 **/
@Service
public class TaskServiceImpl implements TaskService {

    @Override
    public void work(String keyword) {
        try {
            //模拟业务逻辑
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ScheduleTask

package com.example.demo.task;

import com.example.demo.service.TaskService;

/**
 * 定时任务线程类
 *
 * @author zhongxiaojian
 * @date 2020/4/17
 **/
public class ScheduleTask implements Runnable {

    private static final int TIMEOUT = 30000;

    private String id;
    private TaskService service;
    private String keyword;

    public String getId() {
        return id;
    }

    /**
     * @param id      任务ID
     * @param service 业务类
     * @param keyword 关键字参数
     */
    public ScheduleTask(String id, TaskService service, String keyword) {
        this.id = id;
        this.service = service;
        this.keyword = keyword;
    }

    @Override
    public void run() {
        service.work(keyword);
    }
}

ScheduleUtil

package com.example.demo.utils;

import com.example.demo.task.ScheduleTask;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

/**
 * 定时任务工具类
 *
 * @author zhongxiaojian
 * @date 2020/4/17
 **/
public class ScheduleUtil {

    private static ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    private static Map<String, ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();

    static {
        threadPoolTaskScheduler.initialize();
        System.out.println("定时任务线程池启动");
    }

    /**
     * 启动
     *
     * @param scheduleTask 定时任务
     * @param corn         执行时间表达式
     */
    public static boolean start(ScheduleTask scheduleTask, String corn) {
        System.out.println("启动定时任务线程 taskId " + scheduleTask.getId());
        ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler
                .schedule(scheduleTask, new CronTrigger(corn));
        scheduledFutureMap.put(scheduleTask.getId(), scheduledFuture);
        return true;
    }

    /**
     * 取消
     *
     * @param scheduleTask 定时任务
     */
    public static boolean cancel(ScheduleTask scheduleTask) {
        System.out.println("关闭定时任务线程 taskId " + scheduleTask.getId());
        ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(scheduleTask.getId());
        if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
            scheduledFuture.cancel(false);
        }
        scheduledFutureMap.remove(scheduleTask.getId());
        return true;
    }

    /**
     * 修改
     *
     * @param scheduleTask 定时任务
     * @param corn         执行时间表达式
     */
    public static boolean reset(ScheduleTask scheduleTask, String corn) {
        //先取消定时任务
        cancel(scheduleTask);
        //然后启动新的定时任务
        start(scheduleTask, corn);
        return true;
    }
}

总结

这样我们就完成了动态添加定时任务的接口,这里留了一个小小的问题,系统程序重启之后怎么办?其实也简单,只要把创建的任务的参数持久化到数据库,然后每次程序启动的时候读取出来初始化一遍就OK了,如果还不知道怎么办的同学就关注下方的公众号加小编的微信,小编手把手教你,包教包会。—————END—————
喜欢本文的朋友,欢迎关注公众号 BUG速递,分享程序员每天写出来的bug或工作中的问题

在这里插入图片描述

  • 16
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值