springboot 動態修改定時任務


1、靜態定時

      1)啟動類加上注解@EnableScheduling

@EnableAsync
@EnableScheduling
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
@ComponentScan("com.example")
public class DemoApplication {

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

    @Autowired
    private Environment env;
    //destroy-method="close"的作用是當數據庫連接不使用的時候,就把該連接重新放到數據池中,方便下次使用調用.
    //@Bean(destroyMethod =  "close")
    public DataSource dataSource() {
        //
    }

    //為了打包springboot項目
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder builder) {
        return builder.sources(this.getClass());
    }
}

      2) 定時類加上@Component、定時方法添加@Scheduled(cron = "")即可  這里有一個在線生成cron的網站

@Component
public class ScheduledTask {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Scheduled(cron = "0 30 * * * ?")
    @Async("asyncServiceExecutor")
    public void AutoGetAllData(){
        //
    }
}

這里默認的定時任務是單線程的,如果有多個任務同時觸發,只能一個一個執行,如果想實現多線程,可以自行建立線程池工具類,再通過@Async()引用即可

線程池工具類

@Configuration
@EnableAsync
public class ExecutorConfig {

    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);

    @Bean
    public Executor asyncServiceExecutor(){
        logger.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心線程數
        executor.setCorePoolSize(5);
        //配置最大線程數
        executor.setMaxPoolSize(5);
        //配置隊列大小
        executor.setQueueCapacity(99999);
        //配置線程池中的線程的名稱前綴
        executor.setThreadNamePrefix("async-service-");
        // rejection-policy:當pool已經達到max size的時候,如何處理新任務
        // CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //執行初始化
        executor.initialize();
        return executor;
    }
}

2、動態定時

動態定時是通過繼承SchedulingConfigurer,重寫configureTasks方法實現的。

實現過程:

1、前台修改定時任務,更新數據庫

2、定時器根據ID或者名稱查詢數據庫中該方法的cron,注意修改之后不會立即實現,需等當前任務完成之后,下一次執行。這里有更詳細的博客

@Component
public class MyDynamicTask implements SchedulingConfigurer {

    @Autowired
    private TaskService taskService;
    private static Logger log = LoggerFactory.getLogger(MyDynamicTask.class);
    private String cron = "0/10 * * * * ? ";

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar){
        if(getTrigger("InsertCaiYanShiJian")!=null){
            scheduledTaskRegistrar.addTriggerTask(InsertCaiYanShiJian(), getTrigger("InsertCaiYanShiJian"));
        }
        if(getTrigger("AutoGetAllData")!=null){
           scheduledTaskRegistrar.addTriggerTask(AutoGetAllData(), getTrigger("AutoGetAllData"));
       }
    }

    //定時任務1
    private Runnable InsertCaiYanShiJian(){
        return new Runnable() {
        //注入Dao @Autowired
private OrigDLDao origDLDao; @Autowired private OrigRtvDao origRtvDao; @Override public void run() { log.info("InsertCaiYanShiJian 每33秒執行一次,時間為:" + new Date(System.currentTimeMillis()));
          //注入失敗,通過工具類注入  
if(origDLDao==null){ this.origDLDao = SpringBeanFactoryUtils.getBean(OrigDLDao.class); } if(origRtvDao==null){ this.origRtvDao = SpringBeanFactoryUtils.getBean(OrigRtvDao.class); } //具體邏輯 } }; }     //定時任務2 private Runnable AutoGetAllData(){ return new Runnable(){ @Autowired private UtilDao utilDao; @Autowired private Client client; @Override public void run() { // 業務邏輯 log.info("AutoGetAllData 每十秒執行一次,時間為:" + new Date(System.currentTimeMillis())); if(utilDao==null){ this.utilDao = SpringBeanFactoryUtils.getBean(UtilDao.class); } if(client==null){ this.client = SpringBeanFactoryUtils.getBean(Client.class); } //具體邏輯 } }; }
     private Trigger getTrigger(String taskName){ return new Trigger(){ @Override public Date nextExecutionTime(TriggerContext triggerContext) { // 觸發器 if(getCron(taskName)==""){ return null; }else { CronTrigger trigger = new CronTrigger(getCron(taskName)); return trigger.nextExecutionTime(triggerContext); } } }; }
//通過任務名稱獲取Task,Task是一個對象,有任務ID,任務名稱,任務描述,cron等
public String getCron(String taskName) { Task task = this.taskService.getTaskByName(taskName); if(task==null){ return ""; }else { return task.getTaskCron(); } } }
SpringBeanFactoryUtils工具類
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringBeanFactoryUtils implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    /**
     * 獲取靜態變量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 從靜態變量applicationContext中得到Bean, 自動轉型為所賦值對象的類型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        //System.out.println(name);
        String[] str = applicationContext.getBeanDefinitionNames();
        for (String string : str) {
            System.out.println("..." + string);
        }
        return (T) applicationContext.getBean(name);
    }
    /**
     * 從靜態變量applicationContext中得到Bean, 自動轉型為所賦值對象的類型.
     */
    public static <T> T getBean(Class<T> requiredType) {
        return applicationContext.getBean(requiredType);
    }
    /**
     * 實現ApplicationContextAware接口, 注入Context到靜態變量中.
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM