溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么用SpringBoot實現(xiàn)動態(tài)添加定時任務(wù)功能

發(fā)布時間:2022-02-28 14:46:30 來源:億速云 閱讀:570 作者:iii 欄目:開發(fā)技術(shù)

這篇“怎么用SpringBoot實現(xiàn)動態(tài)添加定時任務(wù)功能”文章的知識點大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么用SpringBoot實現(xiàn)動態(tài)添加定時任務(wù)功能”文章吧。

最近的需求有一個自動發(fā)布的功能, 需要做到每次提交都要動態(tài)的添加一個定時任務(wù)

怎么用SpringBoot實現(xiàn)動態(tài)添加定時任務(wù)功能

代碼結(jié)構(gòu)

怎么用SpringBoot實現(xiàn)動態(tài)添加定時任務(wù)功能

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;
/**
 * 調(diào)度器配置
 *
 * @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. 定時任務(wù)類型枚舉

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;
/**
 * 任務(wù)類型
 *
 * @author Jiahang Li
 * @version 1.0.0
 * @since 2022/2/14 10:16
 */
@AllArgsConstructor
public enum TaskType {
    /**
     * 發(fā)布任務(wù)
     */
    RELEASE(id -> new ReleaseTaskImpl((Long) id)) {
        @Override
        public String getKey(Object params) {
            return Const.RELEASE + "-" + params;
        }
    },
     * 調(diào)度任務(wù)
    SCHEDULER_TASK(id -> new SchedulerTaskImpl((Long) id)) {
            return Const.TASK + "-" + params;
    ;
    private final Function<Object, Runnable> factory;
     * 創(chuàng)建任務(wù)
     *
     * @param params params
     * @return task
    public Runnable create(Object params) {
        return factory.apply(params);
    }
     * 獲取 key
     * @return key
    public abstract String getKey(Object params);
}

這個枚舉的作用是生成定時任務(wù)的 runnable 和 定時任務(wù)的唯一值, 方便后續(xù)維護

3. 實際執(zhí)行任務(wù)實現(xiàn)類

package com.orion.ops.handler.scheduler.impl;
 
import com.orion.ops.service.api.ApplicationReleaseService;
import com.orion.spring.SpringHolder;
import lombok.extern.slf4j.Slf4j;
/**
 * 發(fā)布任務(wù)實現(xiàn)
 *
 * @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("定時執(zhí)行發(fā)布任務(wù)-觸發(fā) releaseId: {}", releaseId);
        applicationReleaseService.runnableAppRelease(releaseId, true);
}

4. 定時任務(wù)包裝器

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;
/**
 * 定時 任務(wù)包裝器
 *
 * @author Jiahang Li
 * @version 1.0.0
 * @since 2022/2/14 10:34
 */
public class TimedTask {
    /**
     * 任務(wù)
     */
    private Runnable runnable;
     * 異步執(zhí)行
    private volatile ScheduledFuture<?> future;
    public TimedTask(Runnable runnable) {
        this.runnable = runnable;
    }
     * 提交任務(wù) 一次性
     *
     * @param scheduler scheduler
     * @param time      time
    public void submit(TaskScheduler scheduler, Date time) {
        this.future = scheduler.schedule(runnable, time);
     * 提交任務(wù) cron表達式
     * @param trigger   trigger
    public void submit(TaskScheduler scheduler, Trigger trigger) {
        this.future = scheduler.schedule(runnable, trigger);
     * 取消定時任務(wù)
    public void cancel() {
        if (future != null) {
            future.cancel(true);
        }
}

這個類的作用是包裝實際執(zhí)行任務(wù), 以及提供調(diào)度器的執(zhí)行方法

5. 任務(wù)注冊器 (核心)

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;
/**
 * 任務(wù)注冊器
 *
 * @author Jiahang Li
 * @version 1.0.0
 * @since 2022/2/14 10:46
 */
@Component
public class TaskRegister implements DisposableBean {
    private final Map<String, TimedTask> taskMap = Maps.newCurrentHashMap();
    @Resource
    @Qualifier("taskScheduler")
    private TaskScheduler scheduler;
    /**
     * 提交任務(wù)
     *
     * @param type   type
     * @param time   time
     * @param params params
     */
    public void submit(TaskType type, Date time, Object params) {
        // 獲取任務(wù)
        TimedTask timedTask = this.getTask(type, params);
        // 執(zhí)行任務(wù)
        timedTask.submit(scheduler, time);
    }
     * @param cron   cron
    public void submit(TaskType type, String cron, Object params) {
        timedTask.submit(scheduler, new CronTrigger(cron));
     * 獲取任務(wù)
    private TimedTask getTask(TaskType type, Object params) {
        // 生成任務(wù)
        Runnable runnable = type.create(params);
        String key = type.getKey(params);
        // 判斷是否存在任務(wù)
        if (taskMap.containsKey(key)) {
            throw Exceptions.init(MessageConst.TASK_PRESENT);
        }
        TimedTask timedTask = new TimedTask(runnable);
        taskMap.put(key, timedTask);
        return timedTask;
     * 取消任務(wù)
    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();
}

這個類提供了執(zhí)行, 提交任務(wù)的api, 實現(xiàn) DisposableBean 接口, 便于在bean銷毀時將任務(wù)一起銷毀

6. 使用

    @Resource
    private TaskRegister taskRegister;
    
    /**
     * 提交發(fā)布
     */
    @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);
        // 提交任務(wù)
            taskRegister.submit(TaskType.RELEASE, request.getTimedReleaseTime(), id);
        return id;
    }

以上就是關(guān)于“怎么用SpringBoot實現(xiàn)動態(tài)添加定時任務(wù)功能”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI