springboot自带定时器实现定时任务的开启关闭以及定时时间可以配置

小虾米 阅读:1138 2020-03-20 14:57:24 评论:0

一、序言:

最近项目需要用到定时任务,需要完成一个定时功能。经过了解,项目中目前实现定时任务,一般有三种选择,一是用Java自带的timer类。稍微看了一下,可以实现大部分的指定频率的任务的调度(timer.schedule()),也可以实现关闭和开启(timer.cancle)。但是用其来实现某天的某个时间或者某月的某一天调度任务有点不方便。

二是采用Quartz 调度器实现。这是一个功能很强大的开源的专门用于定时任务调度的框架,也很好的和springboot整合,缺点:配置复杂,需要花费一定的时间去了解和研究。

三是spring3.0以后自带的scheduletask任务调度,可以实现quartz的大部分功能,不需要额外引用jar,也不需要另外配置。而且支持注解和配置文件两种。

我选择的是最直接简单的第三种。下面简单介绍下springboot自带的定时器来实现定时任务。

二、定时任务代码:

简单介绍:开启和关闭相当于写出一个个接口,暴露给前端,通过页面来实现定时器 的开关操作。由于我是后台开发人员,这里只给出后台代码。

1、controller层代码:

 
package com.left.controller; 
 
import com.left.Result; 
import com.left.runnable.MyRunnable1; 
import com.left.runnable.MyRunnable2; 
import com.left.util.ResultUtils; 
import com.left.utils.YouXinConfiguration; 
import io.swagger.annotations.Api; 
import io.swagger.annotations.ApiOperation; 
import lombok.extern.slf4j.Slf4j; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.scheduling.Trigger; 
import org.springframework.scheduling.TriggerContext; 
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 
import org.springframework.scheduling.support.CronTrigger; 
import org.springframework.web.bind.annotation.PostMapping; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
import java.util.Date; 
import java.util.concurrent.ScheduledFuture; 
 
/** 
 * <pre> 
 *    @author : orange 
 *    @e-mail : 495314527@qq.com 
 *    @time   : 2018/8/28 16:15 
 *    @desc   : 定时任务 
 *    @version: 1.0 
 * </pre> 
 */ 
@Slf4j 
@RestController 
@Api(description = "定时任务") 
@RequestMapping("/quartz/task") 
public class DynamicTaskController { 
 
    @Autowired 
    private YouXinConfiguration youXinConfiguration; 
 
    @Autowired 
    private ThreadPoolTaskScheduler threadPoolTaskScheduler; 
 
    private ScheduledFuture<?> future1; 
 
    private ScheduledFuture<?> future2; 
 
    @Bean 
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() { 
        return new ThreadPoolTaskScheduler(); 
    } 
 
    @PostMapping("/startCron1") 
    @ApiOperation("开始定时任务1") 
    public Result startCron1() { 
 
        future1 = threadPoolTaskScheduler.schedule(new MyRunnable1(),new Trigger(){ 
            @Override 
            public Date nextExecutionTime(TriggerContext triggerContext){ 
                return new CronTrigger(youXinConfiguration.getCorn1()).nextExecutionTime(triggerContext); 
            } 
        }); 
 
        System.out.println("DynamicTask.startCron1()"); 
 
        return ResultUtils.success(); 
 
    } 
 
    @PostMapping("/stopCron1") 
    @ApiOperation("关闭定时任务1") 
    public Result stopCron1() { 
        if (future1 != null) { 
            future1.cancel(true); 
        } 
        System.out.println("DynamicTask.stopCron1()"); 
        return ResultUtils.success(); 
    } 
 
 
    @PostMapping("/startCron2") 
    @ApiOperation("开始定时任务2") 
    public Result startCron2() { 
 
        future2 = threadPoolTaskScheduler.schedule(new MyRunnable2(),new Trigger(){ 
            @Override 
            public Date nextExecutionTime(TriggerContext triggerContext){ 
                return new CronTrigger(youXinConfiguration.getCorn2()).nextExecutionTime(triggerContext); 
            } 
        }); 
 
        System.out.println("DynamicTask.startCron2()"); 
 
        return ResultUtils.success(); 
 
    } 
 
    @PostMapping("/stopCron2") 
    @ApiOperation("关闭定时任务2") 
    public Result stopCron2() { 
        if (future2 != null) { 
            future2.cancel(true); 
        } 
        System.out.println("DynamicTask.stopCron2()"); 
        return ResultUtils.success(); 
    } 
 
} 

这里面我写了两组定时器的开关操作。这层代码中所引用类的介绍:

ThreadPoolTaskScheduler:线程池任务调度类,能够开启线程池进行任务调度。ThreadPoolTaskScheduler.schedule()方法会创建一个定时计划ScheduledFuture,在这个方法需要添加两个参数,Runnable(线程接口类) 和CronTrigger(定时任务触发器)

YouXinConfiguration:自己写的读取yml文件中数据的类,我是通过这个类来读取yml文件中cron时间表达式的,从而可以达到定时时间可配置的效果。当然了也可以把这个时间表达式写成通过前端页面传入的形式。但是我觉得这种时间参数改动频率很小,写在yml配置文件足以。这个类下面会给出代码。

MyRunnable1与MyRunnable2类:这两个类都是实现了Runnable接口,重写了run方法,定时任务的逻辑代码就是在这个里面实现的。代码会在下面给出。

2、YouXinConfiguration类代码:

 
package com.left.utils; 
 
import lombok.Data; 
import lombok.EqualsAndHashCode; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.stereotype.Component; 
 
 
/** 
 * <pre> 
 *    @author : orange 
 *    @e-mail : 495314527@qq.com 
 *    @time   : 2018/8/28 16:15 
 *    @desc   :  
 *    @version: 1.0 
 * </pre> 
 */ 
@Data 
@Component 
@ConfigurationProperties(prefix = "youxing") 
@EqualsAndHashCode(callSuper = false) 
public class YouXinConfiguration { 
    private String corn1; 
    private String corn2; 
} 

3、yml文件(定时时间的配置的在最下面的youxing字段)

 
server: 
  port: 8002 
spring: 
    application: 
      name: dubbo-client-orange 
    redis: 
      database: 0 
      host: 127.0.0.1 
      port: 6379 
      password: 
      jedis: 
        pool: 
          max-active: 8 
          max-wait: -1 
          max-idle: 8 
          min-idle: 0 
          timeout: 10000 
    dubbo: 
      server: false 
      registry: redis://127.0.0.1:6379 
      consumer: 
        check: false 
      timeout: 10000 
youxing: 
  corn1: 0/10 * * * * ? 
  corn2: 0/5 * * * * ? 
 

4、MyRunnable1与MyRunnable2基本一样:

 
package com.left.runnable; 
 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
public class MyRunnable1 implements Runnable { 
    @Override 
    public void run() { 
        System.out.println("first DynamicTask," + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 
    } 
}
 
package com.left.runnable; 
 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
public class MyRunnable2 implements Runnable { 
    @Override 
    public void run() { 
        System.out.println("second DynamicTask," + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 
    } 
}

5、启动SpringBoot项目,访问 http://localhost:8080/swagger-ui.html

6、控制台打印效果:

标签:Spring Boot
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号