java定时服务
定时服务执行时只能查询当前数据库中已有的数据,新增的数据不能即时加入到定时任务中
为解决此问题,双重任务嵌套
package org.springblade.demo.job;
import org.apache.commons.lang3.StringUtils;
import org.springblade.demo.entity.PatrolTask;
import org.springblade.demo.mapper.PatrolTaskMapper;
import org.springblade.demo.util.ScheduledUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.TriggerTask;
import org.springframework.scheduling.support.CronTrigger;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
/**
* @author jbei
* @since 2022-06-07 15:50
*/
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
//笔者这里配合数据库来实现动态添加。方便查询数据库这里使用JdbcTemplate
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
PatrolTaskMapper patrolTaskMapper;
private ScheduledTaskRegistrar taskRegistrar;
private Set<ScheduledFuture<?>> scheduledFutures = null;
private Map<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<>();
private List<String> idList = new ArrayList<>();
private String rentNames = "";
/**
* 这个方法在Spring初始化的时候会帮我们执行,这里也会拉取数据库内需要执行的任务,进行添加到定时器里。
*
* @param scheduledTaskRegistrar
*/
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
List<TriggerTask> list = new ArrayList<>();
//循环添加任务
TriggerTask triggerTask = new TriggerTask(() -> {
//定时任务
//TODO 每分钟获取所有计划任务的情况
toPushPatrolTask(taskRegistrar);
}, triggerContext -> {
return new CronTrigger("*/30 * * * * ?").nextExecutionTime(triggerContext);
});
list.add(triggerTask);
//将任务列表注册到定时器
scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
scheduledTaskRegistrar.setTriggerTasksList(list);
this.taskRegistrar = scheduledTaskRegistrar;
}
private void toPushPatrolTask(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//查询出来当前数据库中存储的所有有效的任务
List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from asset_patrol where is_deleted=0 and cron IS not NULL and cron !=''");
Map<String, String> keyCronMap = new HashMap();
//循环添加任务
maps.forEach(t -> {
//TODO 去重
String patrolId = t.get("id").toString();
String cron = t.get("cron").toString();
if (!idList.contains(patrolId + cron)) {
idList.add(patrolId + cron);
TriggerTask triggerTask = new TriggerTask(() -> {
addPatrolTask(t);
}, triggerContext -> {
return new CronTrigger(cron).nextExecutionTime(triggerContext);
});
//将任务列表注册到定时器
addTask(patrolId, triggerTask);
}
});
}
private Runnable getRunnable(Map<String, Object> map) {
return new Runnable() {
@Override
public void run() {
addPatrolTask(map);
try {
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
private Trigger getTrigger(String cron) {
return new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger trigger = new CronTrigger(cron);
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
};
}
/**
* 根据传入的巡查计划,新增巡查任务
*
* @param time
*/
public LocalDateTime parseStringToDateTime(String time, String format) {
time=time.substring(0,time.length()-2);
DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
return LocalDateTime.parse(time, df);
}
private void addPatrolTask(Map<String, Object> t) {
String assetids = t.get("scope_ids") == null ? "" : t.get("scope_ids").toString();
assetids = assetids.substring(0, assetids.length() - 1);
assetids = assetids.replace(";", "','");
List<String> rentNamesList = jdbcTemplate.queryForList("select rent_name from asset_contract where is_deleted=0 and now()>rent_start_date and now() < rent_end_date and id in" +
" (select contract_id from asset_contract_assets where asset_id in ('" + assetids + "'))", String.class);
rentNames = StringUtils.join(rentNamesList, ";");
System.out.println("定时任务:" + t.get("cron").toString() + "添加任务,时间" + LocalDateTime.now().toLocalTime());
PatrolTask patrolTask = new PatrolTask();
// 设置任务对应的巡查计划
patrolTask.setPatrolId(((Number) t.get("id")).longValue());
patrolTask.setPatrolPersonid(t.get("patrol_personid") != null ? t.get("patrol_personid").toString() : "");
// 设置任务状态是未领取
patrolTask.setStatus(0);
patrolTask.setCycle((Integer)t.get("cycle"));
// 设置巡查时间
patrolTask.setPatrolDate(LocalDateTime.now());
patrolTask.setCreateTime(new Date());
patrolTask.setCreateDept(((Number) t.get("create_dept")).longValue());
patrolTask.setRemark(null == t.get("remark") ? "" : t.get("remark").toString());
patrolTask.setRentNames(rentNames);
// 设置巡查生效时间
// TODO
if (t.get("effective_date")!=null){
patrolTask.setEffectiveDate(parseStringToDateTime(t.get("effective_date").toString(),"yyyy-MM-dd HH:mm:ss"));
}
patrolTask.setPlanName(null == t.get("plan_name") ? "" : t.get("plan_name").toString());
patrolTask.setPatrolPersonname(null == t.get("patrol_personname") ? "" : t.get("patrol_personname").toString());
patrolTask.setScope(null == t.get("scope") ? "" : t.get("scope").toString());
patrolTask.setScopeIds(null == t.get("scope_ids") ? "" : t.get("scope_ids").toString());
patrolTask.setAssetRoadArea(null == t.get("asset_road_area") ? "" : t.get("asset_road_area").toString());
int a = patrolTaskMapper.insert(patrolTask);
}
/**
* 添加任务
*
* @param taskId
* @param triggerTask
*/
public void addTask(String taskId, TriggerTask triggerTask) {
//如果定时任务id已存在,则取消原定时器,从新创建新定时器,这里也是个更新定时任务的过程。
if (taskFutures.containsKey(taskId)) {
System.out.println("the taskId[" + taskId + "] 取消,重新添加");
cancelTriggerTask(taskId);
}
TaskScheduler scheduler = taskRegistrar.getScheduler();
ScheduledFuture<?> future = scheduler.schedule(triggerTask.getRunnable(), triggerTask.getTrigger());
getScheduledFutures().add(future);
taskFutures.put(taskId, future);
}
/**
* 获取任务列表
*/
private Set<ScheduledFuture<?>> getScheduledFutures() {
if (scheduledFutures == null) {
try {
scheduledFutures = (Set<ScheduledFuture<?>>) ScheduledUtils.getProperty(taskRegistrar, "scheduledTasks");
} catch (NoSuchFieldException e) {
throw new SchedulingException("not found scheduledFutures field.");
}
}
return scheduledFutures;
}
/**
* 取消任务
*/
public void cancelTriggerTask(String taskId) {
ScheduledFuture<?> future = taskFutures.get(taskId);
if (future != null) {
future.cancel(true);
}
taskFutures.remove(taskId);
getScheduledFutures().remove(future);
}
}