介绍两种实现方式;配置实现和读取数据库定时任务配置实现。

配置实现比较简单。直接撸代码:

package com;

import java.util.Properties;

import org.apache.ibatis.mapping.DatabaseIdProvider; import org.apache.ibatis.mapping.VendorDatabaseIdProvider; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ImportResource; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication @ImportResource("classpath:/config.xml") @EnableAutoConfiguration
@ComponentScan
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan({"com..model..mapper","com.*.task"}) @EnableScheduling public class StartApplication {

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

@Bean
public DatabaseIdProvider getDatabaseIdProvider() {
   
}

} 注:在启动类上加注解 @EnableScheduling @MapperScan 扫描定时任务配置文件的位置。 其他地方无需关注。

定时任务配置类: package com.*.task;

import java.text.SimpleDateFormat; import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service;

@Service public class RunTaskConfig {

private static final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
//初始延迟1秒,每隔2秒
@Scheduled(fixedRateString = "2000",initialDelay = 1000)
public void testFixedRate(){
    System.out.println("fixedRateString,当前时间:" +format.format(new Date()));
}

//每次执行完延迟2秒
@Scheduled(fixedDelayString= "2000")
public void testFixedDelay(){
    System.out.println("fixedDelayString,当前时间:" +format.format(new Date()));
}
//每隔3秒执行一次
@Scheduled(cron="0/3 * * * * ?")
public void testCron(){
    System.out.println("cron,当前时间:" +format.format(new Date()));
}

}

配置完成,项目启动后配置的定时任务会自动执行。

Springboot 定时任务 的数据库实现方式: 数据表实体 id , 执行类, 执行方法, 是否生效, 时间表达式;

SpringBoot 定时任务实现原理:启动Spring 会扫描@Scheduled 注解,读取注解配置信息。 获取定时任务,解析,注册成可执行的定时任务。

数据库活动定时任务实现具体代码如下 package com.tansun.task;

import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.ScheduledExecutorService;

import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.NamedBeanHolder; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.CronTask; import org.springframework.scheduling.config.ScheduledTask; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.support.CronTrigger; import org.springframework.scheduling.support.ScheduledMethodRunnable; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import com.tansun.model.system.dao.RunTaskDao; import com.tansun.model.system.dao.RunTaskDaoImpl; import com.tansun.model.system.dao.RunTaskSqlBulider; import com.tansun.model.system.entity.RunTask; import com.tansun.web.framework.util.BeanUtil; /***

  • 定时任务启动类,从数据库读取定时任务配置。监控定时任务运行。

  • @author kangx */ @Component("BeanDefineConfigue") public class EventListen implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware{

    public static final String DEFAULT_TASK_SCHEDULER_BEAN_NAME = "taskScheduler";

    protected final Log logger = LogFactory.getLog(getClass()); // 任务调度对象引用 private Object scheduler;

    private String beanName;

    private BeanFactory beanFactory; // 配置环境上下文信息 private ApplicationContext applicationContext; // 任务调度注册中心,监控定时任务,设置定时任务启动触发器。 private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();

    // 定时任务执行体 private final Map<Object, Set<ScheduledTask>> scheduledTasks = new IdentityHashMap<Object, Set<ScheduledTask>>(16);

    public Object getScheduler() { return scheduler; }

    public void setScheduler(Object scheduler) { this.scheduler = scheduler; } //EmbeddedValueResolver embeddedValueResolver=new EmbeddedValueResolver(null); @Override public void onApplicationEvent(ContextRefreshedEvent event) {

     try {
     	RunTaskDao runTaskDao = BeanUtil.getBean(RunTaskDaoImpl.class);
         RunTaskSqlBulider runTaskSqlBulider = new RunTaskSqlBulider();
         //查找启动状态的定时任务
         runTaskSqlBulider.andIsWorkEqualTo("1");
         int count = runTaskDao.countBySqlBulider(runTaskSqlBulider);
         List<RunTask> list = new ArrayList<>(); 
         if(count>0){
         	list = runTaskDao.selectListBySqlBulider(runTaskSqlBulider);
         }
         for(RunTask runtask:list){
         	//定时任务对象解析,装配及注册
         	processScheduled(runtask);
         }
         // 定时任务注册,启动定时任务
         finishRegistration();		     
         
     } catch (Exception e) {
     	e.printStackTrace();
     }
    

    }

    /**

    • 定时任务注册 */ private void finishRegistration() { if (this.scheduler != null) { this.registrar.setScheduler(this.scheduler); } if (this.beanFactory instanceof ListableBeanFactory) { Map<String, SchedulingConfigurer> configurers = ((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class); for (SchedulingConfigurer configurer : configurers.values()) { configurer.configureTasks(this.registrar); } } if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) { try { this.registrar.setTaskScheduler(resolveSchedulerBean(TaskScheduler.class, false)); } catch (NoUniqueBeanDefinitionException ex) { try { this.registrar.setTaskScheduler(resolveSchedulerBean(TaskScheduler.class, true)); } catch (NoSuchBeanDefinitionException ex2) { // 日志记录 ex2.printStackTrace(); } } catch (NoSuchBeanDefinitionException ex) { // Search for ScheduledExecutorService bean next... try { this.registrar.setScheduler(resolveSchedulerBean(ScheduledExecutorService.class, false)); } catch (NoUniqueBeanDefinitionException ex2) { try { this.registrar.setScheduler(resolveSchedulerBean(ScheduledExecutorService.class, true)); } catch (NoSuchBeanDefinitionException ex3) { // 日志记录 ex3.printStackTrace(); } } catch (NoSuchBeanDefinitionException ex2) { // 异常日志 ex2.printStackTrace(); } } } this.registrar.afterPropertiesSet(); } private <T> T resolveSchedulerBean(Class<T> schedulerType, boolean byName) { if (byName) { T scheduler = this.beanFactory.getBean(DEFAULT_TASK_SCHEDULER_BEAN_NAME, schedulerType); if (this.beanFactory instanceof ConfigurableBeanFactory) { ((ConfigurableBeanFactory) this.beanFactory).registerDependentBean( DEFAULT_TASK_SCHEDULER_BEAN_NAME, this.beanName); } return scheduler; } else if (this.beanFactory instanceof AutowireCapableBeanFactory) { NamedBeanHolder<T> holder = ((AutowireCapableBeanFactory) this.beanFactory).resolveNamedBean(schedulerType); if (this.beanFactory instanceof ConfigurableBeanFactory) { ((ConfigurableBeanFactory) this.beanFactory).registerDependentBean( holder.getBeanName(), this.beanName); } return holder.getBeanInstance(); } else { return this.beanFactory.getBean(schedulerType); } }

    /**

    • 定时任务装配

    • @throws ClassNotFoundException

    • @throws SecurityException

    • @throws NoSuchMethodException */ protected void processScheduled(RunTask runTask) throws Exception{ try { Class clazz = Class.forName(runTask.getExecuteClass()); Object bean = clazz.newInstance(); Method method = clazz.getMethod(runTask.getExecuteMethod(), null); Method invocableMethod = AopUtils.selectInvocableMethod(method, clazz); Runnable runnable = new ScheduledMethodRunnable(bean, invocableMethod); boolean processedSchedule = false;

       Set<ScheduledTask> tasks = new LinkedHashSet<ScheduledTask>(4);
       String cron = runTask.getTimeExpression();
       if (StringUtils.hasText(cron)) {
       	processedSchedule = true;
       	String zone = "";
       	TimeZone timeZone;
       	if (StringUtils.hasText(zone)) {
       		timeZone = StringUtils.parseTimeZoneString(zone);
       	}
       	else {
       		timeZone = TimeZone.getDefault();
       	}
       	tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));
       }
       // Finally register the scheduled tasks
       synchronized (this.scheduledTasks) {
       	Set<ScheduledTask> registeredTasks = this.scheduledTasks.get(bean);
       	if (registeredTasks == null) {
       		registeredTasks = new LinkedHashSet<ScheduledTask>(4);
       		this.scheduledTasks.put(bean, registeredTasks);
       	}
       	registeredTasks.addAll(tasks);
       }
      

      } catch (IllegalArgumentException ex) { // 日志 ex.printStackTrace(); } } /**

    • 获取环境上下文信息 */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; if (this.beanFactory == null) { this.beanFactory = applicationContext; } } }