springboot 动态加载定时任务

该代码示例展示了如何使用Spring Boot实现动态定时任务管理。通过监听数据库中任务配置的变化,自动调整任务的执行间隔。当任务配置更新时,会取消原有任务并重新设置执行时间,确保任务按照最新配置执行。
@Configuration
@EnableScheduling
public class CompleteScheduleConfig implements SchedulingConfigurer {


    @Autowired
    TaskService taskService;

    private List<TaskBean> list;

    private ScheduledTaskRegistrar mysCheduledTaskRegistrar;

    @Autowired
    SpringContextUtil springContextUtil;

    private static AtomicBoolean run= new AtomicBoolean(false);

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        this.mysCheduledTaskRegistrar=scheduledTaskRegistrar;
        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(40));
        intTask();
    }

    public ScheduledFuture<?> addTask(Runnable runnable, Trigger trigger){
        return  mysCheduledTaskRegistrar.getScheduler().schedule(runnable,trigger);
    }

    /**
     * 初始化定时任务
     * @author 张志兴
     * @date 2021/9/30 14:21
     */
    public void intTask(){
        TaskScheduler taskScheduler = mysCheduledTaskRegistrar.getScheduler();
        ScheduledFuture<?> schedule = taskScheduler.schedule(
                () -> {
                        list.forEach((taskBean -> {
                            if (stopTask(taskBean) && taskBean.getTaskRun()) {
                                ScheduledFuture<?> scheduledFuture = addTask(() -> new DyRunMethod(springContextUtil, taskBean.getTaskSpringBean(), taskBean.getTaskMethod()).executeMethod(taskBean), triggerContext -> {
                                    return new CronTrigger(taskBean.getTaskCron()).nextExecutionTime(triggerContext);
                                });
                                //将定时任务加入到map缓存中
                                StaticFileds.taskFutures.put(taskBean.getTaskId(), new TaskFutureBean(scheduledFuture, taskBean.getTaskCron()));
                            }
                        }
                                )
                        );
                }
                ,
                triggerContext -> {
                    //定时3秒去数据库加载配置信息
                    list=taskService.getTask();
                    return new CronTrigger("0/3 * * * * ?").nextExecutionTime(triggerContext);
                }
        );
    }

    /**
     * 检查运行中的任务的执行时间和新加载的运行时候是否一致,
     * 如果一致,则不做任何操作
     * 如果不一致,则取消运行中的任务,重新设置新的执行时间
     * @author 张志兴
     * @date 2021/9/30 14:19
     * @param taskBean
     * @return boolean
     */
    public  boolean stopTask(TaskBean taskBean){
        if(StaticFileds.taskFutures.containsKey(taskBean.getTaskId())){
            TaskFutureBean taskFutureBean=StaticFileds.taskFutures.get(taskBean.getTaskId());
                    if(!Objects.equals(taskBean.getTaskCron(),taskFutureBean.getExpression())){
                        taskFutureBean.getSchedule().cancel(false);
                        StaticFileds.taskFutures.remove(taskBean.getTaskId());
                        System.out.println("定时任务"+taskBean.getTaskId()+"执行被取消,将重新设置执行时间");
                        return true;
                    }else {
                        return false;
                    }
        }
        return true;
    }

}

public class StaticFileds {

    public StaticFileds() {

    }



    public StaticFileds getInstance()
    {
        return SingletonHolder.INSTANCE;
    }
    private static class SingletonHolder
    {
        private static final StaticFileds INSTANCE = new StaticFileds();
    }

    public static Map<String, TaskFutureBean> taskFutures = new ConcurrentHashMap<String, TaskFutureBean>();

    public static CopyOnWriteArrayList<String> runTaskIds=new CopyOnWriteArrayList<String>();

}
public interface TaskInterface {

    void execute(Object object);

}

@TableName("task_table")
public class TaskBean {
    public TaskBean(String taskId, String taskCron){
        this.taskId=taskId;
        this.taskCron=taskCron;
    }

    //任务Id
    @TableField(value ="taskId",jdbcType = JdbcType.NVARCHAR)
    private  String taskId;

    //执行时间
    @TableField(value ="taskCron",jdbcType = JdbcType.NVARCHAR)
    private  String taskCron;

    //任务调用SpringBean
    @TableField(value ="taskSpringBean",jdbcType = JdbcType.NVARCHAR)
    private  String taskSpringBean;

    //任务使用的方法
    @TableField(value ="taskMethod",jdbcType = JdbcType.NVARCHAR)
    private  String taskMethod;

    //任务是否被启用
    @TableField(value = "taskRun",jdbcType = JdbcType.CHAR)
    private  boolean taskRun;

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public String getTaskCron() {
        return taskCron;
    }

    public void setTaskCron(String taskCron) {
        this.taskCron = taskCron;
    }

    public String getTaskSpringBean() {
        return taskSpringBean;
    }

    public void setTaskSpringBean(String taskSpringBean) {
        this.taskSpringBean = taskSpringBean;
    }

    public String getTaskMethod() {
        return taskMethod;
    }

    public void setTaskMethod(String taskMethod) {
        this.taskMethod = taskMethod;
    }

    public boolean getTaskRun() {
        return taskRun;
    }

    public void setTaskRun(boolean taskRun) {
        this.taskRun = taskRun;
    }
}
public class TaskFutureBean {
    private ScheduledFuture<?> schedule;
    private String expression;

    public TaskFutureBean(ScheduledFuture<?> schedule, String expression){
        this.schedule=schedule;
        this.expression=expression;
    }

    public ScheduledFuture<?> getSchedule() {
        return schedule;
    }

    public void setSchedule(ScheduledFuture<?> schedule) {
        this.schedule = schedule;
    }

    public String getExpression() {
        return expression;
    }

    public void setExpression(String expression) {
        this.expression = expression;
    }
}

@Service("taskService")
public class TaskServiceImpl implements TaskService, TaskInterface {


    @Autowired
    private TaskMapper taskMapper;

    @Override
    public List<TaskBean> getTask() {
        List<TaskBean> list=taskMapper.selectByMap(new HashMap());
        return list;
    }

    /**
     * 定时任务自定义方法名
     * @author 张志兴
     * @date 2021/9/30 10:21
     * @param taskBean
     */
    @Override
    public void customTaskMethod(TaskBean taskBean) {
            StaticFileds.runTaskIds.add(taskBean.getTaskId());
            //处理逻辑
            System.out.println("方法名:customTaskMethod正在执行[任务ID"+taskBean.getTaskId()+"执行时间"+ LocalDateTime.now().toLocalTime()+"]");
    }


    /**
     * 定时默认方法
     * @author 张志兴
     * @date 2021/9/30 10:19
     * @param object
     */
    @Override
    public void execute(Object object) {
        TaskBean taskBean= (TaskBean) object;
            StaticFileds.runTaskIds.add(taskBean.getTaskId());
            //处理逻辑
            System.out.println("方法名:execute正在执行[任务ID"+taskBean.getTaskId()+"执行时间"+ LocalDateTime.now().toLocalTime()+"]");
    }
}

/**
 * @author 张志兴
 * @date 2021年09月29日15:28
 */
public class DyRunMethod {
    private SpringContextUtil springContextUtil;
    private String bean;
    private String method;
    
    /**
     * 
     * @author 张志兴
     * @date 2021/9/29 15:50
     * @param springContextUtil
     * @param bean
     * @param method 
     * @return null      
     */
    public DyRunMethod(SpringContextUtil springContextUtil,String bean,String method) {
        this.springContextUtil = springContextUtil;
        this.bean=bean;
        this.method=method;
    }

    /**
     * 
     * @author 张志兴
     * @date 2021/9/29 15:50
     * @param springContextUtil
     * @param bean 
     * @return null      
     */
    public DyRunMethod(SpringContextUtil springContextUtil,String bean) {
        this.springContextUtil = springContextUtil;
        this.bean=bean;
        this.method="execute";
    }


    /**
     * 
     * @author 张志兴
     * @date 2021/9/29 15:35
     */
    public void executeMethod() {
        Object ServiceImplType = springContextUtil.getBean(this.bean);
        Method[] methods = ServiceImplType.getClass().getMethods();
        for(Method m:methods){
            if(m.getName().equals(this.method)){
                try {
                    m.invoke(ServiceImplType);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     *
     * @author 张志兴
     * @date 2021/9/29 15:36
     * @param obj 参数
     */
    public void executeMethod(Object obj)  {
        Object ServiceImplType = springContextUtil.getBean(this.bean);
        Method[] methods = ServiceImplType.getClass().getMethods();
        for(Method m:methods){
            if(m.getName().equals(this.method)){
                try {
                    m.invoke(ServiceImplType,obj);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

CREATE TABLE `task_table` (
  `taskId` varchar(30) DEFAULT NULL,
  `taskCron` varchar(30) DEFAULT NULL,
  `taskSpringBean` varchar(200) DEFAULT NULL,
  `taskMethod` varchar(200) DEFAULT 'execute',
  `taskRun` char(2) DEFAULT '1'
)

在这里插入图片描述
执行一段时间后,手动到数据库中将任务1的执行间隔为13秒改为7秒。整个执行结果如下:

方法名:execute正在执行[任务ID1执行时间14:15:13.015]
方法名:customTaskMethod正在执行[任务ID2执行时间14:15:17.002]
方法名:execute正在执行[任务ID1执行时间14:15:26.003]
方法名:customTaskMethod正在执行[任务ID2执行时间14:15:34.014]
方法名:execute正在执行[任务ID1执行时间14:15:39.010]
方法名:customTaskMethod正在执行[任务ID2执行时间14:15:51.015]
方法名:execute正在执行[任务ID1执行时间14:15:52.010]
方法名:execute正在执行[任务ID1执行时间14:16:00.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:16:00.001]
方法名:execute正在执行[任务ID1执行时间14:16:13]
方法名:customTaskMethod正在执行[任务ID2执行时间14:16:17.015]
定时任务1执行被取消,将重新设置执行时间
###############任务1由间隔13秒执行一次自动变为了7秒执行一次
方法名:execute正在执行[任务ID1执行时间14:16:21.007]
方法名:execute正在执行[任务ID1执行时间14:16:28.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:16:34.012]
方法名:execute正在执行[任务ID1执行时间14:16:35.010]
方法名:execute正在执行[任务ID1执行时间14:16:42.003]
方法名:execute正在执行[任务ID1执行时间14:16:49.008]
方法名:customTaskMethod正在执行[任务ID2执行时间14:16:51.014]
方法名:execute正在执行[任务ID1执行时间14:16:56.007]
方法名:customTaskMethod正在执行[任务ID2执行时间14:17:00.010]
方法名:execute正在执行[任务ID1执行时间14:17:00.010]
方法名:execute正在执行[任务ID1执行时间14:17:07.010]
方法名:execute正在执行[任务ID1执行时间14:17:14.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:17:17.005]
方法名:execute正在执行[任务ID1执行时间14:17:21.005]
方法名:execute正在执行[任务ID1执行时间14:17:28.008]
方法名:customTaskMethod正在执行[任务ID2执行时间14:17:34.004]
方法名:execute正在执行[任务ID1执行时间14:17:35.012]
方法名:execute正在执行[任务ID1执行时间14:17:42.008]
方法名:execute正在执行[任务ID1执行时间14:17:49.003]
方法名:customTaskMethod正在执行[任务ID2执行时间14:17:51.010]
方法名:execute正在执行[任务ID1执行时间14:17:56.001]
方法名:execute正在执行[任务ID1执行时间14:18:00.011]
方法名:customTaskMethod正在执行[任务ID2执行时间14:18:00.011]
方法名:execute正在执行[任务ID1执行时间14:18:07.015]
方法名:execute正在执行[任务ID1执行时间14:18:14.011]
方法名:customTaskMethod正在执行[任务ID2执行时间14:18:17.014]
方法名:execute正在执行[任务ID1执行时间14:18:21.015]
方法名:execute正在执行[任务ID1执行时间14:18:28.012]
方法名:customTaskMethod正在执行[任务ID2执行时间14:18:34.010]
方法名:execute正在执行[任务ID1执行时间14:18:35.005]
方法名:execute正在执行[任务ID1执行时间14:18:42.014]
方法名:execute正在执行[任务ID1执行时间14:18:49.002]
方法名:customTaskMethod正在执行[任务ID2执行时间14:18:51.008]
方法名:execute正在执行[任务ID1执行时间14:18:56.001]
方法名:execute正在执行[任务ID1执行时间14:19:00.011]
方法名:customTaskMethod正在执行[任务ID2执行时间14:19:00.012]
方法名:execute正在执行[任务ID1执行时间14:19:07.001]
方法名:execute正在执行[任务ID1执行时间14:19:14.011]
方法名:customTaskMethod正在执行[任务ID2执行时间14:19:17.007]
方法名:execute正在执行[任务ID1执行时间14:19:21.012]
方法名:execute正在执行[任务ID1执行时间14:19:28.009]
方法名:customTaskMethod正在执行[任务ID2执行时间14:19:34.006]
方法名:execute正在执行[任务ID1执行时间14:19:35.015]
方法名:execute正在执行[任务ID1执行时间14:19:42.002]
方法名:execute正在执行[任务ID1执行时间14:19:49.007]
方法名:customTaskMethod正在执行[任务ID2执行时间14:19:51.012]
方法名:execute正在执行[任务ID1执行时间14:19:56.005]
方法名:customTaskMethod正在执行[任务ID2执行时间14:20:00.006]
方法名:execute正在执行[任务ID1执行时间14:20:00.006]
方法名:execute正在执行[任务ID1执行时间14:20:07.002]
方法名:execute正在执行[任务ID1执行时间14:20:14.011]
方法名:customTaskMethod正在执行[任务ID2执行时间14:20:17.001]
方法名:execute正在执行[任务ID1执行时间14:20:21.006]
方法名:execute正在执行[任务ID1执行时间14:20:28.002]
方法名:customTaskMethod正在执行[任务ID2执行时间14:20:34.002]
方法名:execute正在执行[任务ID1执行时间14:20:35.012]
方法名:execute正在执行[任务ID1执行时间14:20:42.003]
方法名:execute正在执行[任务ID1执行时间14:20:49.009]
方法名:customTaskMethod正在执行[任务ID2执行时间14:20:51.014]
方法名:execute正在执行[任务ID1执行时间14:20:56.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:21:00.006]
方法名:execute正在执行[任务ID1执行时间14:21:00.006]
方法名:execute正在执行[任务ID1执行时间14:21:07.011]
方法名:execute正在执行[任务ID1执行时间14:21:14.002]
方法名:customTaskMethod正在执行[任务ID2执行时间14:21:17.014]
方法名:execute正在执行[任务ID1执行时间14:21:21.012]
方法名:execute正在执行[任务ID1执行时间14:21:28.006]
方法名:customTaskMethod正在执行[任务ID2执行时间14:21:34.001]
方法名:execute正在执行[任务ID1执行时间14:21:35.014]
方法名:execute正在执行[任务ID1执行时间14:21:42.008]
方法名:execute正在执行[任务ID1执行时间14:21:49.008]
方法名:customTaskMethod正在执行[任务ID2执行时间14:21:51.002]
方法名:execute正在执行[任务ID1执行时间14:21:56.014]
方法名:execute正在执行[任务ID1执行时间14:22:00.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:22:00.001]
方法名:execute正在执行[任务ID1执行时间14:22:07.012]
方法名:execute正在执行[任务ID1执行时间14:22:14.010]
方法名:customTaskMethod正在执行[任务ID2执行时间14:22:17.007]
方法名:execute正在执行[任务ID1执行时间14:22:21.011]
方法名:execute正在执行[任务ID1执行时间14:22:28.008]
方法名:customTaskMethod正在执行[任务ID2执行时间14:22:34.004]
方法名:execute正在执行[任务ID1执行时间14:22:35.001]
方法名:execute正在执行[任务ID1执行时间14:22:42.012]
方法名:execute正在执行[任务ID1执行时间14:22:49.012]
方法名:customTaskMethod正在执行[任务ID2执行时间14:22:51.001]
方法名:execute正在执行[任务ID1执行时间14:22:56.009]
方法名:customTaskMethod正在执行[任务ID2执行时间14:23:00.009]
方法名:execute正在执行[任务ID1执行时间14:23:00.010]
方法名:execute正在执行[任务ID1执行时间14:23:07.010]
方法名:execute正在执行[任务ID1执行时间14:23:14.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:23:17.008]
方法名:execute正在执行[任务ID1执行时间14:23:21.010]
方法名:execute正在执行[任务ID1执行时间14:23:28.014]
方法名:customTaskMethod正在执行[任务ID2执行时间14:23:34.007]
方法名:execute正在执行[任务ID1执行时间14:23:35.002]
方法名:execute正在执行[任务ID1执行时间14:23:42.005]
方法名:execute正在执行[任务ID1执行时间14:23:49.015]
方法名:customTaskMethod正在执行[任务ID2执行时间14:23:51.004]
方法名:execute正在执行[任务ID1执行时间14:23:56.011]
方法名:execute正在执行[任务ID1执行时间14:24:00.001]
方法名:customTaskMethod正在执行[任务ID2执行时间14:24:00.001]
方法名:execute正在执行[任务ID1执行时间14:24:07.008]

到此为止,功能已经基本实现。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值