欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot動(dòng)態(tài)定時(shí)功能實(shí)現(xiàn)方案詳解

 更新時(shí)間:2022年11月15日 15:20:37   作者:smileNicky  
在SpringBoot項(xiàng)目中簡(jiǎn)單使用定時(shí)任務(wù),不過由于要借助cron表達(dá)式且都提前定義好放在配置文件里,不能在項(xiàng)目運(yùn)行中動(dòng)態(tài)修改任務(wù)執(zhí)行時(shí)間,實(shí)在不太靈活?,F(xiàn)在我們就來實(shí)現(xiàn)可以動(dòng)態(tài)修改cron表達(dá)式的定時(shí)任務(wù),感興趣的可以了解一下

業(yè)務(wù)場(chǎng)景

基于上篇程序,做了一版動(dòng)態(tài)定時(shí)程序,然后發(fā)現(xiàn)這個(gè)定時(shí)程序需要在下次執(zhí)行的時(shí)候會(huì)加載新的時(shí)間,所以如果改了定時(shí)程序不能馬上觸發(fā),所以想到一種方法,在保存定時(shí)程序的時(shí)候?qū)ron表達(dá)式傳過去,然后觸發(fā)定時(shí)程序,下面看看怎么實(shí)現(xiàn)

環(huán)境準(zhǔn)備

開發(fā)環(huán)境

  • JDK 1.8
  • SpringBoot2.2.1
  • Maven 3.2+

開發(fā)工具

  • IntelliJ IDEA
  • smartGit
  • Navicat15

實(shí)現(xiàn)方案

基于上一版進(jìn)行改進(jìn):

  • 先根據(jù)選擇的星期生成cron表達(dá)式,保存到數(shù)據(jù)庫(kù)里,同時(shí)更改cron表達(dá)式手動(dòng)觸發(fā)定時(shí)程序加載最新的cron表達(dá)式
  • 根據(jù)保存的cron表達(dá)式規(guī)則執(zhí)行定時(shí)程序
  • 通過CommandLineRunner設(shè)置啟動(dòng)加載
  • 加上線程池,提高線程復(fù)用率和程序性能

加上ThreadPoolTaskScheduler,支持同步和異步兩種方式:

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@Slf4j
public class ScheduleConfig implements SchedulingConfigurer , AsyncConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler());
    }
    @Bean(destroyMethod="shutdown" , name = "taskScheduler")
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("itemTask-");
        scheduler.setAwaitTerminationSeconds(600);
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        return scheduler;
    }
    @Bean(name = "asyncExecutor")
    public ThreadPoolTaskExecutor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setQueueCapacity(1000);
        executor.setKeepAliveSeconds(600);
        executor.setMaxPoolSize(20);
        executor.setThreadNamePrefix("itemAsyncTask-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    @Override
    public Executor getAsyncExecutor() {
        return asyncExecutor();
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            log.error("異步任務(wù)異常,message {} , method {} , params" , throwable , method , objects);
        };
    }
}

加上一個(gè)SchedulerTaskJob接口:

public interface SchedulerTaskJob{
    void executeTask();
}

AbstractScheduler 抽象類,提供基本的功能

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
@Slf4j
@Component
@Data
public abstract class AbstractScheduler implements SchedulerTaskJob{
    @Resource(name = "taskScheduler")
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    @Override
    public void executeTask() {
        String cron = getCronString();
        Runnable task = () -> {
            // 執(zhí)行業(yè)務(wù)
            doBusiness();
        };
        Trigger trigger = new Trigger()   {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                CronTrigger trigger;
                try {
                    trigger = new CronTrigger(cron);
                    return trigger.nextExecutionTime(triggerContext);
                } catch (Exception e) {
                    log.error("cron表達(dá)式異常,已經(jīng)啟用默認(rèn)配置");
                    // 配置cron表達(dá)式異常,執(zhí)行默認(rèn)的表達(dá)式
                    trigger = new CronTrigger(getDefaultCron());
                    return trigger.nextExecutionTime(triggerContext);
                }
            }
        };
        threadPoolTaskScheduler.schedule(task , trigger);
    }
    protected abstract String getCronString();
    protected abstract void doBusiness();
    protected abstract String getDefaultCron();
}

實(shí)現(xiàn)類,基于自己的業(yè)務(wù)實(shí)現(xiàn),然后事項(xiàng)抽象類,通過模板模式進(jìn)行編程

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
@Service
@Slf4j
@Data
public class ItemSyncScheduler extends AbstractScheduler {
    @Value("${configtask.default.itemsync}")
    private String defaultCron ;
    private String cronString ;
    @Override
    protected String getCronString() {
        if (StrUtil.isNotBlank(cronString))  return cronString;
        SyncConfigModel configModel = syncConfigService.getOne(Wrappers.<SyncConfigModel>lambdaQuery()
                .eq(SyncConfigModel::getBizType, 1)
                .last("limit 1"));
        if (configModel == null) return defaultCron;
        return configModel.getCronStr();
    }
    @Override
    protected void doBusiness() {
        log.info("執(zhí)行業(yè)務(wù)...");
        log.info("執(zhí)行時(shí)間:{}"  , LocalDateTime.now());
       // 執(zhí)行業(yè)務(wù)
    }
    @Override
    protected String getDefaultCron() {
        return defaultCron;
    }
}

如果更改了cron表達(dá)式,程序不會(huì)馬上觸發(fā),所以直接開放一個(gè)接口出來,調(diào)用的時(shí)候,設(shè)置最新的表達(dá)式,然后重新調(diào)用定時(shí)程序

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class ItemSchedulerController {
    private ItemSyncScheduler itemSyncScheduler;
    @Autowired
    public ItemSchedulerController(ItemSyncScheduler itemSyncScheduler) {
        this.itemSyncScheduler= itemSyncScheduler;
    }
    @GetMapping(value = "/updateItemCron")
    @ApiOperation(value = "更新cron表達(dá)式")
    public void updateItemCron(@RequestParam("cronString") String cronString) {
        log.info("更新cron表達(dá)式...");
        log.info("cronString:{}" , cronString);
        itemSyncScheduler.setCronString(cronString);
        itemSyncScheduler.executeTask();
    }
}

實(shí)現(xiàn)CommandLineRunner ,實(shí)現(xiàn)Springboot啟動(dòng)加載

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@Order(1)
public class SchedulerTaskRunner implements CommandLineRunner {
    private ItemSyncScheduler itemSyncScheduler;
    @Autowired
    public SchedulerTaskRunner(ItemSyncScheduler itemSyncScheduler) {
        this.itemSyncScheduler= itemSyncScheduler;
    }
    @Override
    public void run(String... args) throws Exception {
        itemSyncScheduler.executeTask();
    }
}

歸納總結(jié)

基于上一版定時(shí)程序的問題,做了改進(jìn),加上了線程池和做到了動(dòng)態(tài)觸發(fā),網(wǎng)上的資料很多都是直接寫明使用SchedulingConfigurer來實(shí)現(xiàn)動(dòng)態(tài)定時(shí)程序,不過很多都寫明場(chǎng)景,本文通過實(shí)際,寫明實(shí)現(xiàn)方法,本文是在保存定時(shí)程序的時(shí)候,設(shè)置最新的cron表達(dá)式,調(diào)一下接口重新加載,還可以使用canal等中間件監(jiān)聽數(shù)據(jù)表,如果改了就再設(shè)置cron表達(dá)式,然后觸發(fā)程序

到此這篇關(guān)于SpringBoot動(dòng)態(tài)定時(shí)功能實(shí)現(xiàn)方案詳解的文章就介紹到這了,更多相關(guān)SpringBoot動(dòng)態(tài)定時(shí)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot 連接LDAP的方法

    Spring Boot 連接LDAP的方法

    這篇文章主要介紹了Spring Boot 連接LDAP的方法,僅僅涉及基本的使用ODM來快速實(shí)現(xiàn)LDAP增刪改查操作。具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-12-12
  • 使用Spring?Boot如何限制在一分鐘內(nèi)某個(gè)IP只能訪問10次

    使用Spring?Boot如何限制在一分鐘內(nèi)某個(gè)IP只能訪問10次

    有些時(shí)候,為了防止我們上線的網(wǎng)站被攻擊,或者被刷取流量,我們會(huì)對(duì)某一個(gè)ip進(jìn)行限制處理,這篇文章,我們將通過Spring?Boot編寫一個(gè)小案例,來實(shí)現(xiàn)在一分鐘內(nèi)同一個(gè)IP只能訪問10次,感興趣的朋友一起看看吧
    2023-10-10
  • Maven本地存在jar包IDEA依舊爆紅的完美解決方法

    Maven本地存在jar包IDEA依舊爆紅的完美解決方法

    這篇文章主要介紹了Maven本地存在jar包IDEA依舊爆紅的完美解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • 詳談ThreadLocal-單例模式下高并發(fā)線程安全

    詳談ThreadLocal-單例模式下高并發(fā)線程安全

    這篇文章主要介紹了ThreadLocal-單例模式下高并發(fā)線程安全,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • spring事物傳播propagation類別含義詳解

    spring事物傳播propagation類別含義詳解

    這篇文章主要介紹了spring事物傳播propagation類別含義詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java的Semaphore信號(hào)量使用及原理解析

    Java的Semaphore信號(hào)量使用及原理解析

    這篇文章主要介紹了Java的Semaphore信號(hào)量使用及原理解析,Semaphore 通常我們叫它信號(hào)量, 可以用來控制同時(shí)訪問特定資源的線程數(shù)量,通過協(xié)調(diào)各個(gè)線程,以保證合理的使用資源,需要的朋友可以參考下
    2023-12-12
  • slf4j?jcl?jul?log4j1?log4j2?logback各組件系統(tǒng)日志切換

    slf4j?jcl?jul?log4j1?log4j2?logback各組件系統(tǒng)日志切換

    這篇文章主要介紹了slf4j、jcl、jul、log4j1、log4j2、logback的大總結(jié),各個(gè)組件的jar包以及目前系統(tǒng)日志需要切換實(shí)現(xiàn)方式的方法,有需要的朋友可以借鑒參考下
    2022-03-03
  • FeignClient如何通過配置變量調(diào)用配置文件url

    FeignClient如何通過配置變量調(diào)用配置文件url

    這篇文章主要介紹了FeignClient如何通過配置變量調(diào)用配置文件url,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 圖解Spring框架的設(shè)計(jì)理念與設(shè)計(jì)模式

    圖解Spring框架的設(shè)計(jì)理念與設(shè)計(jì)模式

    這篇文章主要通過多圖詳細(xì)解釋Spring框架的設(shè)計(jì)理念與設(shè)計(jì)模式,需要的朋友可以參考下
    2015-08-08
  • SpringCloud使用Zookeeper作為注冊(cè)中心

    SpringCloud使用Zookeeper作為注冊(cè)中心

    這篇文章主要介紹了SpringCloud如何使用Zookeeper作為注冊(cè)中心,幫助大家更好的理解和學(xué)習(xí)使用Zookeeper,感興趣的朋友可以了解下
    2021-04-04

最新評(píng)論