spring建立动态定时任务
1. 创建定时器抽象类
/**
* 定时器抽象类
*
* @author
*
*/
public abstract class ScheduleTask implements Runnable {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public ScheduleTask(String id) {
this.id = id;
}
@Override
public abstract void run();
}
2.写定时任务工具类
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
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.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import www.wensi.com.vmi.task.ScheduleTask;
/**
* 定时任务工具类
*
*/
@Slf4j
@Component
public class ScheduleUtil {
private static ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
private static Map<String, ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();
static {
threadPoolTaskScheduler.initialize();
log.debug("初始化线程池...");
}
/**
* 启动某定时任务,到时间点就运行一次
*
* @param scheduleTask
* @param startTime
*/
public void start(ScheduleTask scheduleTask, Date startTime) {
if (isExist(scheduleTask.getId())) {
log.debug("启动定时任务" + scheduleTask.getId() + "失败,任务已存在");
return;
}
ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.schedule(scheduleTask, startTime);
scheduledFutureMap.put(scheduleTask.getId(), scheduledFuture);
log.debug("启动定时任务" + scheduleTask.getId() + ",执行时间为" + startTime);
}
/**
* 启动某定时任务,以固定周期运行
*
* @param scheduleTask
* @param period
*/
public void start(ScheduleTask scheduleTask, long period) {
if (isExist(scheduleTask.getId())) {
log.debug("启动定时任务" + scheduleTask.getId() + "失败,任务已存在");
return;
}
ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.scheduleAtFixedRate(scheduleTask, period);
scheduledFutureMap.put(scheduleTask.getId(), scheduledFuture);
log.debug("启动定时任务" + scheduleTask.getId() + ",执行周期为" + period + "毫秒");
}
/**
* 启动某定时任务,指定Cron表达式,执行定时任务
*
* @param scheduleTask
* @param period
*/
public void start(ScheduleTask scheduleTask, String cron) {
if (isExist(scheduleTask.getId())) {
log.debug("启动定时任务" + scheduleTask.getId() + "失败,任务已存在");
return;
}
ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.schedule(scheduleTask, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger trigger = new CronTrigger(cron);
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
});
scheduledFutureMap.put(scheduleTask.getId(), scheduledFuture);
log.debug("启动某定时任务" + scheduleTask.getId() + ",指定Cron:{}表达式,执行定时任务 ", cron);
}
/**
* 修改定时任务执行时间
*
* @param scheduleTask
* @param cron
*/
public void reset(ScheduleTask scheduleTask, String cron) {
// 先取消定时任务
String id = scheduleTask.getId();
ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(id);
if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
scheduledFuture.cancel(false);
}
scheduledFutureMap.remove(id);
// 然后启动新的定时任务
scheduledFuture = threadPoolTaskScheduler.schedule(scheduleTask, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger trigger = new CronTrigger(cron);
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
});
scheduledFutureMap.put(id, scheduledFuture);
log.debug("重置定时任务" + id + ",执行时间为" + cron);
}
/**
* 取消某定时任务
*
* @param scheduleTask
*/
public void cancel(ScheduleTask scheduleTask) {
ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(scheduleTask.getId());
if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
scheduledFuture.cancel(false);
}
scheduledFutureMap.remove(scheduleTask.getId());
log.debug("取消定时任务" + scheduleTask.getId());
}
/**
* 修改定时任务执行时间
*
* @param scheduleTask
* @param startTime
*/
public void reset(ScheduleTask scheduleTask, Date startTime) {
// 先取消定时任务
String id = scheduleTask.getId();
ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(id);
if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
scheduledFuture.cancel(false);
}
scheduledFutureMap.remove(id);
// 然后启动新的定时任务
scheduledFuture = threadPoolTaskScheduler.schedule(scheduleTask, startTime);
scheduledFutureMap.put(id, scheduledFuture);
log.debug("重置定时任务" + id + ",执行时间为" + startTime);
}
/**
* 判断某个定时任务是否存在或已经取消
*
* @param id
*/
public Boolean isExist(String id) {
ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(id);
if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
return true;
}
return false;
}
}
3.写springboot bean管理类
import java.lang.annotation.Annotation;
import java.util.Map;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
/**
* springboot bean管理类
*
* @author
*
*/
@Service
public class ManageSpringBeans implements ApplicationContextAware {
private static ApplicationContext context;
public static <T> T getBean(final Class<T> requiredType) {
return context.getBean(requiredType);
}
public static <T> T getBean(final String beanName) {
@SuppressWarnings("unchecked")
final T bean = (T) context.getBean(beanName);
return bean;
}
public static <T> Map<String, T> getBeans(final Class<T> requiredType) {
return context.getBeansOfType(requiredType);
}
public static Map<String, Object> getBeansWithAnnotation(final Class<? extends Annotation> annotationType) {
return context.getBeansWithAnnotation(annotationType);
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) {
context = applicationContext;
}
}
4.写个bean Scheduled
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import lombok.Data;
@Data
public class Scheduled {
private Integer id;
@NotNull(message = "定时器类别不能为空")
private Integer type;
@NotBlank(message = "定时器时间不能为空")
private String cron;
}
5.定时器类,实现定时器抽象类(我这里写一个用来做日志清除的实现类)
/**
* 定时器实现类
*
* @author begoit
*
*/
@Slf4j
public class LogCleanTask extends ScheduleTask {
// 日志清除接口
private LogCleanTaskService logCleanTaskService = ManageSpringBeans.getBean(LogCleanTaskService.class);
public LogCleanTask(String id) {
super(id);
}
@Override
public void run() {
/**
* 要执行的任务
*/
log.debug(new Date() + "任务" + this.getId() + "开始执行任务日志清理任务");
// 清除管理员日志
logCleanTaskService.adminLogClean();
}
}
6.日志清除接口
/**
* 日志清除接口
*
* @author
*
*/
@Component
@Slf4j
public class LogCleanTaskService {
@Autowired
private AdminLogMapper adminLogMapper; // 保存日志的表
/**
* 管理员日志清除
*/
public void adminLogClean() {
// 清除数据。。。
}
}
7.设置日志定时器接口
/**
* 日志定时器接口
*
* @author
*
*/
@Service
@Slf4j
public class ScheduledService {
@Autowired
private ScheduledMapper scheduledMapper; // 查询数据库定时器接口
@Autowired
private ScheduleUtil scheduleUtil; // 定时器工具类
/**
* 设置定时器
*
* @return
*/
public BaseResponse setScheduled(Scheduled scheduled) {
// 将scheduled中的设置保存到数据库中。这里省略
ScheduleTask task = new LogCleanTask("logCleanTask");// new一个具体的执行任务
// 修改定时任务执行时间,cron可以根据数据库查询结果设置
String cron = "0 0 6 * * ?";
scheduleUtil.reset(task, cron);
return new BaseResponse(StatusCode.Success);
}
}
7.创建ScheduledController类
@RestController
@Slf4j
public class ScheduledController {
@Autowired
private ScheduledService scheduledService;
/**
* 设置定时器
*
* @param scheduledList
* @return
*/
@PostMapping("/s/scheduled/setScheduled")
public BaseResponse set(@RequestBody @Valid Scheduled scheduled) {
log.info("设置定时器,scheduled:{}",scheduled);
BaseResponse response = scheduledService.setScheduled(scheduled);
return response;
}
}