SpringBoot 实现动态往数据库中添加时间点,使程序在规定的时间点执行任务
1.依赖引入 配置文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
server:
port: 9094
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root123
driver-class-name: com.mysql.jdbc.Driver
mybatis:
mapper-locations: classpath:com/example/**/mapper/*.xml
type-aliases-package: com.example.demo.dto
2.表以及设计
3.代码实现
3.1 任务添加线程池里面去跑
package com.example.demo.config;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
/**
* @author 胡萝卜
*/
@Component
public class MyScheduling implements SchedulingConfigurer {
/** 定时任务注册器 */
private ScheduledTaskRegistrar taskRegistrar;
private Set<ScheduledFuture<?>> scheduledFutures = null;
/** 存放所有定时任务 */
private Map<String, ScheduledFuture<?>> taskMap = new ConcurrentHashMap<>();
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
this.taskRegistrar = taskRegistrar;
}
@SuppressWarnings("unchecked")
private Set<ScheduledFuture<?>> getScheduledFutures() {
if (scheduledFutures == null) {
try {
scheduledFutures = (Set<ScheduledFuture<?>>) getProperty(taskRegistrar, "scheduledTasks");
}
catch (NoSuchFieldException e) {
throw new SchedulingException("not found scheduledFutures field.");
}
}
return scheduledFutures;
}
/**
* 添加定时任务
* @param taskId 定时任务唯一标识
* @param runnable 定时任务执行的具体逻辑
* @param trigger 下一个定时任务执行时机的触发器
*/
public void addTriggerTask(String taskId, Runnable runnable, Trigger trigger) {
// 若定时任务已经存在,则进行覆盖操作(即先移除)
if (taskMap.containsKey(taskId)) {
removeTriggerTask(taskId);
}
// 添加定时任务
ScheduledFuture<?> schedule = Objects.requireNonNull(taskRegistrar.getScheduler()).schedule(runnable, trigger);
getScheduledFutures().add(schedule);
taskMap.put(taskId, schedule);
}
/**
* 移除定时任务
* @param taskId 定时任务 id
*/
public void removeTriggerTask(String taskId) {
ScheduledFuture<?> future = taskMap.get(taskId);
if (future != null) {
future.cancel(true);
}
taskMap.remove(taskId);
getScheduledFutures().remove(future);
}
public static Field findField(Class<?> clazz, String name) {
try {
return clazz.getField(name);
} catch (NoSuchFieldException ex) {
return findDeclaredField(clazz, name);
}
}
public static Field findDeclaredField(Class<?> clazz, String name) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null) {
return findDeclaredField(clazz.getSuperclass(), name);
}
return null;
}
}
public static Object getProperty(Object obj, String name) throws NoSuchFieldException {
Object value = null;
Field field = findField(obj.getClass(), name);
if (field == null) {
throw new NoSuchFieldException("no such field [" + name + "]");
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
try {
value = field.get(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
field.setAccessible(accessible);
return value;
}
}
3.2 查询数据库,找到数据,添加定时任务
package com.example.demo.service;
import com.example.demo.config.MyScheduling;
import com.example.demo.dto.TaskCron;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author 胡萝卜
*/
@Component
@Slf4j
public class TaskScheduling implements ApplicationRunner {
private Logger log= LoggerFactory.getLogger(TaskScheduling.class);
@Autowired
MyScheduling myScheduling;
@Autowired
TaskCronService taskCronService;
@Override
public void run(ApplicationArguments args) throws Exception {
// 在项目启动后,初始化任务调度器,如果是一个页面去添加时间,就是再添加成功或者修改成功,进行初始化一次
initTaskScheduling();
}
public void initTaskScheduling() {
//查询数据库里面的所以任务
List<TaskCron> taskCrons = taskCronService.selectTaskCron();
for(TaskCron taskCron:taskCrons){
log.info("装载定时任务ID:" + taskCron.getId());
myScheduling.addTriggerTask(String.valueOf(taskCron.getId()), getTaskRunnable(taskCron), getTaskTrigger(taskCron));
}
}
/** 获取指定的任务执行逻辑 */
public Runnable getTaskRunnable(TaskCron taskCron) {
return () -> {
//要操作那些业务逻辑
if (taskCron != null){
//执行业务
taskCronService.updateTaskCron(taskCron.getId());
}
};
}
/** 获取指定任务所属的触发器 */
public Trigger getTaskTrigger(TaskCron taskCron) {
return triggerContext -> {
// 通过获取该用户最近的未完成的日程,解析出下一个通知的发送时间
String cron;
//时间todo
cron=taskCron.getCronTime();
//Task nearestTask = taskService.getNearestTask(groupId);
if (taskCron != null) {
// 任务存在的话,将执行时间解析为 cron 表达式
// 如果时间已经超过了,则立即执行,否则常规解析
log.info("解析出的 cron:" + cron);
}
// 返回执行周期
return new CronTrigger(cron).nextExecutionTime(triggerContext);
};
}
}
mapper.xml
package com.example.demo.service;
import com.example.demo.dto.TaskCron;
import com.example.demo.repository.dao.TaskCronMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author 胡萝卜
*/
@Service
public class TaskCronService {
@Autowired
private TaskCronMapper taskCronMapper;
public void updateTaskCron(Integer id){
taskCronMapper.update(id);
}
public List<TaskCron> selectTaskCron(){
return taskCronMapper.selectTaskCron();
}
}
<update id="update">
update taskCron
set status=1,frequency=frequency+1,updateTime=NOW()
where id=#{id};
</update>
<select id="selectTaskCron" resultMap="BaseResultMap">
select * from taskCron order by id
</select>
4. 结果
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/121426.html