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

 

posted @ 2019-08-20 16:03  听见温暖www  阅读(2774)  评论(0编辑  收藏  举报