SpringBoot 实现动态添加定时任务功能

网友投稿 301 2022-08-24


SpringBoot 实现动态添加定时任务功能

目录代码结构1.配置类2.定时任务类型枚举3.实际执行任务实现类4.定时任务包装器5.任务注册器(核心)6.使用最后

最近的需求有一个自动发布的功能, 需要做到每次提交都要动态的添加一个定时任务

代码结构

1. 配置类

package com.orion.ops.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.scheduling.TaskScheduler;

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

/**

* 调度器配置

*

* @author Jiahang Li

* @version 1.0.0

* @since 2022/2/14 9:51

*/

@EnableScheduling

@Configuration

public class SchedulerConfig {

@Bean

public TaskScheduler taskScheduler() {

ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();

scheduler.setPoolSize(4);

scheduler.setRemoveOnCancelPolicy(true);

scheduler.setThreadNamePrefix("scheduling-task-");

return scheduler;

}

}

2. 定时任务类型枚举

package com.orion.ops.handler.scheduler;

import com.orion.ops.consts.Const;

import com.orion.ops.handler.scheduler.impl.ReleaseTaskImpl;

import com.orion.ops.handler.scheduler.impl.SchedulerTaskImpl;

import lombok.AllArgsConstructor;

import java.util.function.Function;

/**

* 任务类型

*

* @author Jiahang Li

* @version 1.0.0

* @since 2022/2/14 10:16

*/

@AllArgsConstructor

public enum TaskType {

/**

* 发布任务

*/

RELEASE(id -> new ReleaseTaskImpl((Long) id)) {

@Override

public String getKey(Object params) {

return Const.RELEASE + "-" + params;

}

},

* 调度任务

SCHEDULER_TASK(id -> new SchedulerTaskImpl((Long) id)) {

return Const.TASK + "-" + params;

;

private final Function factory;

* 创建任务

*

* @parOrPqyam params params

* @return task

public Runnable create(Object params) {

return factory.apply(params);

}

* 获取 key

* @return key

public abstract String getKey(Object params);

}

这个枚举的作用是生成定时任务的 runnable 和 定时任务的唯一值, 方便后续维护

3. 实际执行任务实现类

package com.orion.ops.handler.scheduler.impl;

import com.orion.ops.service.api.ApplicationReleaseService;

import com.orion.spring.SpringHolder;

import lombok.extern.slf4j.Slf4j;

/**

* 发布任务实现

*

* @author Jiahang Li

* @version 1.0.0

* @since 2022/2/14 10:25

*/

@Slf4j

public class ReleaseTaskImpl implements Runnable {

protected static ApplicationReleaseService applicationReleaseService = SpringHolder.getBean(ApplicationReleaseService.class);

private Long releaseId;

public ReleaseTaskImpl(Long releaseId) {

this.releaseId = releaseId;

}

@Override

public void run() {

log.info("定时执行发布任务-触发 releaseId: {}", releaseId);

applicationReleaseService.runnableAppRelease(releaseId, true);

}

4. 定时任务包装器

package com.orion.ops.handler.scheduler;

import org.springframework.scheduling.TaskScheduler;

import org.springframework.scheduling.Trigger;

import java.util.Date;

import java.util.concurrent.ScheduledFuture;

/**

* 定时 任务包装器

*

* @author Jiahang Li

* @version 1.0.0

* @since 2022/2/14 10:34

*/

public class TimedTask {

/**

* 任务

*/

private Runnable runnable;

* 异步执行

private volatile ScheduledFuture> future;

public TimedTask(Runnable runnable) {

this.runnable = runnable;

}

* 提交任务 一次性

*

* @param scheduler scheduler

* @param time time

public void submit(TaskScheduler scheduler, Date time) {

this.future = scheduler.schedule(runnable, time);

* 提交任务 cron表达式

* @param trigger trigger

public void submit(TaskScheduler scheduler, Trigger trigger) {

this.future = scheduler.schedule(runnable, trigger);

* 取消定时任务

public void cancel() {

if (future != null) {

future.cancel(true);

}

}

这个类的作用是包装实际执行任务, 以及提供调度器的执行方法

5. 任务注册器 (核心)

package com.orion.ops.handler.scheduler;

import com.orion.ops.consts.MessageConst;

import com.orion.utils.Exceptions;

import com.orion.utils.collect.Maps;

import org.springframework.beans.factory.DisposableBean;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.scheduling.TaskScheduler;

import org.springframework.scheduling.support.CronTrigger;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import java.util.Date;

import java.util.Map;

/**

* 任务注册器

*

* @author Jiahang Li

* @version 1.0.0

* @since 2022/2/14 10:46

*/

@Component

public class TaskRegister implements DisposableBean {

private final Map taskMap = Maps.newCurrentHashMap();

@Resource

@Qualifier("taskScheduler")

private TaskScheduler scheduler;

/**

* 提交任务

*

* @param type type

* @param time time

* @param params params

*/

public void submit(TaskType type, Date time, Object params) {

// 获取任务

TimedTask timedTask = this.getTask(type, params);

// 执行任务

timedTask.submit(scheduler, time);

}

* @param cron cron

public void submit(TaskType type, String cron, Object params) {

timedTask.submit(scheduler, new CronTrigger(cron));

* 获取任务

private TimedTask getTask(TaskType type, Object params) {

// 生成任务

Runnable runnable = type.create(params);

String key = type.getKey(params);

// 判断是否存在任务

if (taskMap.containsKey(key)) {

throw Exceptions.init(MessageConst.TASK_PRESENT);

}

TimedTask timedTask = new TimedTask(runnable);

taskMap.put(key, timedTask);

return timedTask;

* 取消任务

public void cancel(TaskType type, Object params) {

TimedTask task = taskMap.get(key);

if (task != null) {

taskMap.remove(key);

task.cancel();

* 是否存在

public boolean has(TaskType type, Object params) {

return taskMap.containsKey(type.getKey(params));

@Override

public void destroy() {

taskMap.values().forEach(TimedTask::cancel);

taskMap.clear();

}

这个类提供了执行, 提交任务的api, 实现 DisposableBean 接口, 便于在bean销毁时将任务一起销毁

6. 使用

@Resource

private TaskRegister taskRegister;

/**

* 提交发布

*/

@RequestMapping("/submit")

@EventLog(EventType.SUBMIT_RELEASE)

public Long submitAppRelease(@RequestBody ApplicationReleaseRequest request) {

Valid.notBlank(request.getTitle());

Valid.notNull(request.getAppId());

Valid.notNull(request.getProfileId());

Valid.notNull(request.getBuildId());

Valid.notEmpty(request.getMachineIdList());

TimedReleaseType timedReleaseType = Valid.notNull(TimedReleaseType.of(request.getTimedRelease()));

if (TimedReleaseType.TIMED.equals(timedReleaseType)) {

Date timedReleaseTime = Valid.notNull(request.getTimedReleaseTime());

Valid.isTrue(timedReleaseTime.compareTo(new Date()) > 0, MessageConst.TIMED_GREATER_THAN_NOW);

}

// 提交

Long id = applicationReleaseService.submitAppRelease(request);

// 提交任务

taskRegister.submit(TaskType.RELEASE, request.getTimedReleaseTime(), id);

return id;

}

最后

这是一个简单的动态添加定时任务的工具, 有很多的改造空间, 比如想持久化可以插入到库中, 定义一个 CommandLineRunner 在启动时将定时任务全部加载, 还可以给任务加钩子自动提交,自动删除等, 代码直接cv一定会报错, 就是一些工具, 常量类会报错, 改改就好了, 本人已亲测可用, 有什么问题可以在评论区沟通


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:python_第一个神经网络(python神经网络编程 豆瓣)
下一篇:python_第一个神经网络(用python实现神经网络)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~