动态定时任务
使用的是springboot自带的定时任务:TaskScheduler,可动态控制定时任务。
定时任务已实现持久化,持久化方式为数据库,所以第一步需要建个存储任务的表,要求要有字段:enable_flag(是否开启任务)、cron_el(cron表达式)、identifier(任务标识符),SQL语句:
`enable_flag` tinyint unsigned DEFAULT '0',
`cron_el` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`identifier` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL
记得代码中引入mysql依赖和配置
- 建持久化的表
可参考建表语句:
表名不建议使用名称
wjjhook_task,因为框架内实体是使用WjjhookTask命名的。建议命名方式为
${projectName}_cron_task
CREATE TABLE `wjjhook_cron_task` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`enable_flag` tinyint unsigned DEFAULT '0' COMMENT '是否开启任务',
`cron_el` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'cron表达式',
`identifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '任务标识符',
`memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '描述',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`del_flag` tinyint unsigned DEFAULT '0' COMMENT '逻辑删除',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_unique_identifier` (`identifier`,`del_flag`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
执行原理:
启动前手动在
@PostConstruct方法中手动向任务池中注册任务(以便扫描到的标识符能匹配到相应任务代码),进行执行。项目启动后会自动调用*
IWjjhookTaskService.queryEnableList()*的数据,进行启动执行。
使用:
-
建表,参考上述建表语句。(再次提醒,表名请勿使用
wjjhook_task!以下以表名wjjhook_cron_task为例) -
创建三个类(实现方法的拓展):
-
sql层:
WjjhookCronTaskMapper.xmlnamespace需要根据自己包名设置
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.demo.mapper.WangjjTaskMapper"><select id="list" resultType="cn.skyisazure.wjjhook.module.WjjhookTaskModule">SELECTenable_flag,cron_el,identifierFROM `wjjhook_cron_task`WHERE del_flag = 0</select><update id="updateTaskByIdentifier">UPDATE `wjjhook_cron_task`SET cron_el = #{cronEl}WHERE identifier = #{identifier}AND del_flag = 0</update><update id="enableTaskByIdentifier">UPDATE `wjjhook_cron_task`SET enable_flag = 1WHERE identifier = #{identifier}AND del_flag = 0</update><update id="disableTaskByIdentifier">UPDATE `wjjhook_cron_task`SET enable_flag = 0WHERE identifier = #{identifier}AND del_flag = 0</update><update id="removeTask">UPDATE `wjjhook_cron_task`SET del_flag = 1WHERE identifier = #{identifier}AND del_flag = 0</update></mapper> -
Dao层:
WjjhookCronTaskMapper该类要被@MapperScan扫描到。
/*** 定时任务* @author wjian*/public interface WangjjTaskMapper {/*** 返回所有定时任务* @return*/List<WjjhookTaskModule> list();/*** 修改定时任务表达式* @param identifier* @param cronEl*/void updateTaskByIdentifier(@Param("identifier") String identifier,@Param("cronEl") String cronEl);/*** 开启定时任务* @param identifier*/void enableTaskByIdentifier(@Param("identifier") String identifier);/*** 禁用定时任务* @param identifier*/void disableTaskByIdentifier(@Param("identifier") String identifier);/*** 删除定时任务* @param identifier*/void removeTask(@Param("identifier") String identifier);} -
实现类:
WjjhookTaskServiceImpl/*** 任务持久化实现类* @author wangjj*/@Service@RequiredArgsConstructorpublic class WjjhookTaskServiceImpl implements IWjjhookTaskService {private final WangjjTaskMapper wangjjTaskMapper;/*** 返回所有定时任务* @return*/@Overridepublic List<WjjhookTaskModule> list() {return wangjjTaskMapper.list();}/*** 修改定时任务表达式** @param identifier* @param cronEl* @return*/@Overridepublic void updateTaskByIdentifier(String identifier, String cronEl) {wangjjTaskMapper.updateTaskByIdentifier(identifier, cronEl);}/*** 开启定时任务* @param identifier* @return*/@Overridepublic void enableTaskByIdentifier(String identifier) {wangjjTaskMapper.enableTaskByIdentifier(identifier);}/*** 禁用定时任务** @param identifier* @return*/@Overridepublic void disableTaskByIdentifier(String identifier) {wangjjTaskMapper.disableTaskByIdentifier(identifier);}/*** 删除定时任务** @param identifier* @return*/@Overridepublic void removeTask(String identifier) {wangjjTaskMapper.removeTask(identifier);}}
-
-
定义任务:
建一个存放定时任务的包:
com.example.core.task,在该包下新建自己的任务类:/*** 打印当前当前时间* @author wangjj*/public class SimpleTask implements Runnable{@Overridepublic void run() {System.out.println("当前时间:"+LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));}} -
注册任务(将第3步中定义的任务注册到任务中):
推荐第二种:自动注册。
-
第一种,手动注册: 在启动类中加入
@PostConstruct注解的方法,注册任务示例:@SpringBootApplication@MapperScan({"com.example.*.mapper"})@EnableWjjhook(apiSelectorPackages = {@ApiSelectorPackage(value = "com.example.demo.controller"),})public class ExampleDemoApplication {public static void main(String[] args) {SpringApplication.run(ExampleDemoApplication.class, args);}/*** 注册任务*/@PostConstructpublic void registrarRunnable(){TaskRegistrar taskRegistrar = SpringUtil.getBean(TaskRegistrar.class);taskRegistrar.register("printTaskPool",new SimpleTask());}} -
第二种,自动注册:
借助于@Task注解,创建任务类,实现接口Runnable
优势:可使用@Autowired、@Resource注入bean,无需通过多余代码进行注入。
@Task(identifier = "simpleTask")public class SimpleTask implements Runnable {@Resourceprivate UserServer userServer;@Overridepublic void run() {System.out.println(getClass().getSimpleName()+",当前时间:"+ LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")));}}
-
最后在数据库中加入任务:
示例:
INSERT INTO `wjjhook_cron_task`(`id`, `enable_flag`, `cron_el`, `identifier`, `memo`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`)VALUES(5, 0, '*/1 * * * * ?', 'demo', '测试用', '2022-12-31 23:59:59', NULL, NULL, NULL, 0);
最后
注册任务那,手动注册,我建议按上述方式去写注册,其实也可以在SpringApplication.run(NiceDemoApplication.class, args);后注册。