1)启动类加上注解@EnableScheduling
@EnableAsync @EnableScheduling @SpringBootApplication @MapperScan("com.example.demo.mapper") @ComponentScan("com.example") public classDemoApplication { public static voidmain(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Autowired privateEnvironment env; //destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用. //@Bean(destroyMethod = "close") publicDataSource dataSource() { //} //为了打包springboot项目 protectedSpringApplicationBuilder configure( SpringApplicationBuilder builder) { return builder.sources(this.getClass()); } }
2) 定时类加上@Component、定时方法添加@Scheduled(cron = "")即可 这里有一个在线生成cron的网站
@Component public classScheduledTask { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Scheduled(cron = "0 30 * * * ?") @Async("asyncServiceExecutor") public voidAutoGetAllData(){ //} }
这里默认的定时任务是单线程的,如果有多个任务同时触发,只能一个一个执行,如果想实现多线程,可以自行建立线程池工具类,再通过@Async()引用即可
线程池工具类
@Configuration @EnableAsync public classExecutorConfig { private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class); @Bean publicExecutor asyncServiceExecutor(){ logger.info("start asyncServiceExecutor"); ThreadPoolTaskExecutor executor = newThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(5); //配置最大线程数 executor.setMaxPoolSize(5); //配置队列大小 executor.setQueueCapacity(99999); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix("async-service-"); //rejection-policy:当pool已经达到max size的时候,如何处理新任务 //CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); returnexecutor; } }
动态定时是通过继承SchedulingConfigurer,重写configureTasks方法实现的。
实现过程:
1、前台修改定时任务,更新数据库
2、定时器根据ID或者名称查询数据库中该方法的cron,注意修改之后不会立即实现,需等当前任务完成之后,下一次执行。这里有更详细的博客
@Component public class MyDynamicTask implementsSchedulingConfigurer { @Autowired privateTaskService taskService; private static Logger log = LoggerFactory.getLogger(MyDynamicTask.class); private String cron = "0/10 * * * * ? "; @Override public voidconfigureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar){ if(getTrigger("InsertCaiYanShiJian")!=null){ scheduledTaskRegistrar.addTriggerTask(InsertCaiYanShiJian(), getTrigger("InsertCaiYanShiJian")); } if(getTrigger("AutoGetAllData")!=null){ scheduledTaskRegistrar.addTriggerTask(AutoGetAllData(), getTrigger("AutoGetAllData")); }} //定时任务1 privateRunnable InsertCaiYanShiJian(){ return newRunnable() {
//注入Dao @Autowired privateOrigDLDao origDLDao; @Autowired privateOrigRtvDao origRtvDao; @Override public voidrun() { log.info("InsertCaiYanShiJian 每33秒执行一次,时间为:" + newDate(System.currentTimeMillis()));
//注入失败,通过工具类注入 if(origDLDao==null){ this.origDLDao = SpringBeanFactoryUtils.getBean(OrigDLDao.class); } if(origRtvDao==null){ this.origRtvDao = SpringBeanFactoryUtils.getBean(OrigRtvDao.class); } //具体逻辑} }; } //定时任务2 privateRunnable AutoGetAllData(){ return newRunnable(){ @Autowired privateUtilDao utilDao; @Autowired privateClient client; @Override public voidrun() { //业务逻辑 log.info("AutoGetAllData 每十秒执行一次,时间为:" + newDate(System.currentTimeMillis())); if(utilDao==null){ this.utilDao = SpringBeanFactoryUtils.getBean(UtilDao.class); } if(client==null){ this.client = SpringBeanFactoryUtils.getBean(Client.class); } //具体逻辑} }; }
privateTrigger getTrigger(String taskName){ return newTrigger(){ @Override publicDate nextExecutionTime(TriggerContext triggerContext) { //触发器 if(getCron(taskName)==""){ return null; }else{ CronTrigger trigger = newCronTrigger(getCron(taskName)); returntrigger.nextExecutionTime(triggerContext); } } }; }
//通过任务名称获取Task,Task是一个对象,有任务ID,任务名称,任务描述,cron等 publicString getCron(String taskName) { Task task = this.taskService.getTaskByName(taskName); if(task==null){ return ""; }else{ returntask.getTaskCron(); }} }
SpringBeanFactoryUtils工具类
importorg.springframework.beans.BeansException; importorg.springframework.context.ApplicationContext; importorg.springframework.context.ApplicationContextAware; importorg.springframework.stereotype.Component; @Component public class SpringBeanFactoryUtils implementsApplicationContextAware { private staticApplicationContext applicationContext; /*** 获取静态变量中的ApplicationContext. */ public staticApplicationContext getApplicationContext() { returnapplicationContext; } /*** 从静态变量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) { returnapplicationContext.getBean(requiredType); } /*** 实现ApplicationContextAware接口, 注入Context到静态变量中. */@Override public void setApplicationContext(ApplicationContext applicationContext) throwsBeansException { this.applicationContext =applicationContext; }