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; }