最近项目需要用到定时任务,需要完成一个定时功能。经过了解,项目中目前实现定时任务,一般有三种选择,一是用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;
/**
*
* @author : orange
* @e-mail : [email protected]
* @time : 2018/8/28 16:15
* @desc : 定时任务
* @version: 1.0
*
*/
@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;
/**
*
* @author : orange
* @e-mail : [email protected]
* @time : 2018/8/28 16:15
* @desc :
* @version: 1.0
*
*/
@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、控制台打印效果: