Spring-Task定时任务, (springboot项目, 动态设置时间) -- Demo
SpringBoot + SpringTask + SpringDataJPA
业务:
用户选择 自动关闭
后, 可以选择一个时间(格式为yyyy-MM-dd hh:mm),时间到后触发定时任务,关闭或开启系统(修改状态)
精确到秒倒计时会出错(未知), 所以就规定用户不能选秒, 业务逻辑也是可以的(不太好).
核心代码:
DynamicTaskController :
/**
* 定时任务接口
*
* @author wqkeep
* @date 2020/6/10 14:51
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/XXXXXX/task")
public class DynamicTaskController extends BaseController {
//BaseController 主要用于调用JSONResponse ,给JSONResponse 中的参数赋值,this.success(Object data)就是这样
//JSONResponse 封装好的返回结果,有 是否成功success,数据data,消息提示msg,状态码status
private final TaskServiceImpl taskServiceImpl;
/**
* 开启报名通道定时任务
*
* @param id 系统id
* @param sysStatus 系统状态
* @param countDownTime 倒计时时间
* @return JSONResponse 封装好的返回结果,有 是否成功success,数据data,消息提示msg,状态码status
* @throws OperationException 封装好的自定义异常信息
*/
@PostMapping("/XXXXXX/startCron")
public JSONResponse startCron(Long id, Integer sysStatus, @RequestParam("date") String countDownTime) throws OperationException {
taskServiceImpl.startCron(id, sysStatus,countDownTime);
return this.success(SysConst.SUCCESS);
}
/**
* 关闭当前线程定时任务
*
* @return JSONResponse
*/
@PostMapping("/XXXXXX/stopCron")
public JSONResponse stopCron() {
taskServiceImpl.stopCron();
return this.success(SysConst.SUCCESS);
}
/**
* TODO 定时任务存在问题
*
* 目前可以实现倒计时的功能, 但系统如果要集群就会存在问题(关闭不了当前线程, 用户可能会修改多个不同线程的定时任务).
*
*/
}
TaskServiceImpl:
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.stereotype.Service;
import javax.transaction.Transactional;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
/**
* 定时任务
*
* @author wqkeep
* @date 2020/6/10 17:31
*/
@Slf4j
@Service
@Transactional(rollbackOn = RuntimeException.class)
public class TaskServiceImpl implements TaskService {
@Autowired
private TaskRepository taskRepository; //(PO)实体类Task 对应的Repository
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
private ScheduledFuture<?> future;
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
/**
* 开启报名通道定时任务
*
* @param id 系统id
* @param sysStatus 系统状态
* @param countDownTime 倒计时时间
* @throws OperationException 自定义异常信息
*/
public void startCron(Long id, Integer sysStatus, String countDownTime) throws OperationException {
String currentThread = Thread.currentThread().getName();
log.info("DynamicTask 报名通道定时任务开启: 当前线程 " + currentThread);
String strDateFormat = "yyyy-MM-dd HH:mm";
SimpleDateFormat sd = new SimpleDateFormat(strDateFormat);
Date countDownDate = null;
try {
countDownDate = sd.parse(countDownTime);
} catch (Exception e) {
throw new OperationException("字符串转换日期失败");
}
String cron = CronDateUtils.getCron(countDownDate);
//task为自定义的定时任务实体类 我这里主要存储cron表达式和定时任务具体时间,需要定时任务的系统名字,只有一个定时任务需求,所以写死了(不好)
Task task = new Task();
task.setId(1L);
task.setCron(cron);
task.setName("XXXXX系统");
task.setRemark("自动开启关闭");
task.setCountDownTime(countDownDate);
//保存 自定义的定时任务实体类task
taskRepository.save(task);
if (future != null) {
future.cancel(true);
}
future = threadPoolTaskScheduler.schedule(new Runnable() {
@SneakyThrows
@Override
public void run() {
//业务代码, 我这里是修改系统状态为关闭或开启
stopCron();
log.info("DynamicTask 报名通道定时任务停止: 当前线程 " + currentThread);
}
}, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
});
}
/**
* 关闭当前线程定时任务
*/
public void stopCron() {
if (future != null) {
future.cancel(true);
}
}
}
cron表达式和日期转换工具类CronDateUtils :
import com.zjxf.config.exception.custom.OperationException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 定时任务cron表达式与Date之间的转换
*
* @author wqkeep
* @date 2020/6/10 14:51
*/
public class CronDateUtils {
//自定义cron表达式格式 可以修改
private static final String CRON_DATE_FORMAT = "0/1 mm HH dd MM ?";
/***
* Date转换为cron表达式
*
* @param date 时间
* @return cron类型的日期
*/
public static String getCron(final Date date){
SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
String formatTimeStr = "";
if (date != null) {
formatTimeStr = sdf.format(date);
}
return formatTimeStr;
}
/**
* cron表达式转换为Date
*
* @param cron Quartz cron的类型的日期
* @return Date日期
* @throws OperationException 自定义异常信息
*/
public static Date getDate(final String cron) throws OperationException {
if(cron == null) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
Date date = null;
try {
date = sdf.parse(cron);
} catch (Exception e) {
throw new OperationException("转换失败");
}
return date;
}
}
参考博客:
https://blog.csdn.net/weixin_37591536/article/details/82150933