⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/chenping1993/article/details/108274814 「龙池小生」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

业务场景描述:定时任务的任务名称,cron(定时任务表达式),定时任务开关,存储在数据库表中。在不重启项目的情况下,修改定时任务表达式,可以实时获取新的定时任务执行时间规则;修改定时任务执行状态,可以随时开关定时任务。

使用技术:基于接口 SchedulingConfigurer

1、建表 管理定时任务

DROP TABLE IF EXISTS `scheduled`;
CREATE TABLE `scheduled` (
`name` varchar(20) DEFAULT NULL,
`cron` varchar(30) DEFAULT NULL,
`open` tinyint(1) DEFAULT NULL COMMENT '1开启, 其他为关闭'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of scheduled
-- ----------------------------
INSERT INTO `scheduled` VALUES ('demo1', '0/5 * * * * ?', '1');
INSERT INTO `scheduled` VALUES ('demo2', '0/6 * * * * ?', '1');

2、代码实现

定时任务配置类:

package com.example.demo.scheduled;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
* @Description: 基于接口SchedulingConfigurer的动态定时任务
* @Author:
*/
@Configuration
@EnableScheduling
public abstract class ConfigurerSchedulingDemo implements SchedulingConfigurer {

//定时任务周期表达式
private String cron;
/**
* @Description: 重写配置定时任务的方法
* @param: scheduledTaskRegistrar
* @return: void
* @Author:
*/
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(taskScheduler());
scheduledTaskRegistrar.addTriggerTask(
//执行定时任务
() ->
{
taskService();
},
//设置触发器
triggerContext -> {

cron = getCron();//获取定时任务周期表达式

CronTrigger trigger = new CronTrigger(cron);

return trigger.nextExecutionTime(triggerContext);
}
);

}

@Bean
public Executor taskScheduler() {
//设置线程名称
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
//创建线程池
return Executors.newScheduledThreadPool(5, namedThreadFactory);
}

/**
* @Description: 执行定时任务
* @param:
* @return: void
* @Author:
*/
public abstract void taskService();

/**
* @Description: 获取定时任务周期表达式
* @param:
* @return: java.lang.String
* @Author:
* @Date: 2020/8/28
*/
public abstract String getCron();

}

定时任务1

package com.example.demo.scheduled;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.dao.CronMapper;
import com.example.demo.entity.Scheduled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;

/**
* @Description:
* @Author:
*/
@Configuration
public class TaskDemo extends ConfigurerSchedulingDemo {

@Autowired //注入mapper
@SuppressWarnings("all")
CronMapper cronMapper;

@Override
public void taskService() {
Integer open = getOpen();
if (1== open){
System.out.println("定时任务demo1:"
+ LocalDateTime.now()+",线程名称:"+Thread.currentThread().getName()
+ " 线程id:"+Thread.currentThread().getId());
}
}

@Override
public String getCron() {
QueryWrapper<Scheduled> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name","demo1");
String cron = cronMapper.selectOne(queryWrapper).getCron();
return cron;
}

public Integer getOpen() {
QueryWrapper<Scheduled> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "demo1");
Integer open = cronMapper.selectOne(queryWrapper).getOpen();
return open;
}

}

定时任务2

package com.example.demo.scheduled;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.dao.CronMapper;
import com.example.demo.entity.Scheduled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;

/**
* @Description:
* @Author:
*/
@Configuration
public class TaskDemo1 extends ConfigurerSchedulingDemo {

@Autowired //注入mapper
@SuppressWarnings("all")
CronMapper cronMapper;

@Override
public void taskService() {
Integer open = getOpen();
if (1== open){
System.out.println("定时任务demo2:"
+ LocalDateTime.now()+",线程名称:"+Thread.currentThread().getName()
+ " 线程id:"+Thread.currentThread().getId());
}
}

@Override
public String getCron() {
QueryWrapper<Scheduled> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name","demo2");
String cron = cronMapper.selectOne(queryWrapper).getCron();
return cron;
}

public Integer getOpen() {
QueryWrapper<Scheduled> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "demo2");
Integer open = cronMapper.selectOne(queryWrapper).getOpen();
return open;
}
}

效果展示:

启动项目:控制台输出展示

修改数据库 demo1的执行时间为每15秒一次:

关闭demo1的定时任务,将demo1的open状态改为0:

文章目录
  1. 1. 1、建表 管理定时任务
  2. 2. 2、代码实现
  3. 3. 效果展示: