告别硬编码,SpringBoot实现动态增删启停定时任务,非常实用

定时任务执行日志

添加执行定时任务的线程池配置类

@Configuration

public class SchedulingConfig {

@Bean

public TaskScheduler taskScheduler() {

ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();

// 定时任务执行线程池核心线程数

taskScheduler.setPoolSize(4);

taskScheduler.setRemoveOnCancelPolicy(true);

taskScheduler.setThreadNamePrefix(“TaskSchedulerThreadPool-”);

return taskScheduler;

}

}

添加ScheduledFuture的包装类。ScheduledFuture是ScheduledExecutorService定时任务线程池的执行结果。

public final class ScheduledTask {

volatile ScheduledFuture<?> future;

/**

* 取消定时任务

*/

public void cancel() {

ScheduledFuture<?> future = this.future;

if (future != null) {

future.cancel(true);

}

}

}

添加Runnable接口实现类,被定时任务线程池调用,用来执行指定bean里面的方法。

public class SchedulingRunnable implements Runnable {

private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class);

private String beanName;

private String methodName;

private String params;

public SchedulingRunnable(String beanName, String methodName) {

this(beanName, methodName, null);

}

public SchedulingRunnable(String beanName, String methodName, String params) {

this.beanName = beanName;

this.methodName = methodName;

this.params = params;

}

@Override

public void run() {

logger.info(“定时任务开始执行 - bean:{},方法:{},参数:{}”, beanName, methodName, params);

long startTime = System.currentTimeMillis();

try {

Object target = SpringContextUtils.getBean(beanName);

Method method = null;

if (StringUtils.isNotEmpty(params)) {

method = target.getClass().getDeclaredMethod(methodName, String.class);

} else {

method = target.getClass().getDeclaredMethod(methodName);

}

ReflectionUtils.makeAccessible(method);

if (StringUtils.isNotEmpty(params)) {

method.invoke(target, params);

} else {

method.invoke(target);

}

} catch (Exception ex) {

logger.error(String.format("定时任务执行异常 - bean:%s,方法:%s,参数:%s ", beanName, methodName, params), ex);

}

long times = System.currentTimeMillis() - startTime;

logger.info(“定时任务执行结束 - bean:{},方法:{},参数:{},耗时:{} 毫秒”, beanName, methodName, params, times);

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

SchedulingRunnable that = (SchedulingRunnable) o;

if (params == null) {

return beanName.equals(that.beanName) &&

methodName.equals(that.methodName) &&

that.params == null;

}

return beanName.equals(that.beanName) &&

methodName.equals(that.methodName) &&

params.equals(that.params);

}

@Override

public int hashCode() {

if (params == null) {

return Objects.hash(beanName, methodName);

}

return Objects.hash(beanName, methodName, params);

}

}

添加定时任务注册类,用来增加、删除定时任务。

@Component

public class CronTaskRegistrar implements DisposableBean {

private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16);

@Autowired

private TaskScheduler taskScheduler;

public TaskScheduler getScheduler() {

return this.taskScheduler;

}

public void addCronTask(Runnable task, String cronExpression) {

addCronTask(new CronTask(task, cronExpression));

}

public void addCronTask(CronTask cronTask) {

if (cronTask != null) {

Runnable task = cronTask.getRunnable();

if (this.scheduledTasks.containsKey(task)) {

removeCronTask(task);

}

this.scheduledTasks.put(task, scheduleCronTask(cronTask));

}

}

public void removeCronTask(Runnable task) {

ScheduledTask scheduledTask = this.scheduledTasks.remove(task);

if (scheduledTask != null)

scheduledTask.cancel();

}

public ScheduledTask scheduleCronTask(CronTask cronTask) {

ScheduledTask scheduledTask = new ScheduledTask();

scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());

return scheduledTask;

}

@Override

public void destroy() {

for (ScheduledTask task : this.scheduledTasks.values()) {

task.cancel();

}

this.scheduledTasks.clear();

}

}

添加定时任务示例类

@Component(“demoTask”)

public class DemoTask {

public void taskWithParams(String params) {

System.out.println(“执行有参示例任务:” + params);

}

public void taskNoParams() {

System.out.println(“执行无参示例任务”);

}

}

定时任务数据库表设计

定时任务数据库表设计

添加定时任务实体类

public class SysJobPO {

/**

* 任务ID

*/

private Integer jobId;

/**

* bean名称

*/

private String beanName;

/**

* 方法名称

*/

private String methodName;

/**

* 方法参数

*/

private String methodParams;

/**

* cron表达式

*/

private String cronExpression;

/**

* 状态(1正常 0暂停)

*/

private Integer jobStatus;

/**

* 备注

*/

private String remark;

/**

* 创建时间

*/

private Date createTime;

/**

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。

我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。

不管是查缺补漏还是深度学习都能有非常不错的成效,需要的话记得帮忙点个赞支持一下

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

讲义、实战项目、讲解视频,并且后续会持续更新**

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-2hYr4JsW-1712714773032)]

最后

很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。

我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。

不管是查缺补漏还是深度学习都能有非常不错的成效,需要的话记得帮忙点个赞支持一下

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-Xp2Jv5Ge-1712714773033)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值