spring 定时任务

设计思路参考于jeecgboot,因 jeecgboot 中引入了 quartz 框架,要建许多表,我只需要简单的定时任务即可,所以写了个简化版的定时任务。先上代码,再分析。

CREATE TABLE `sys_quartz_job` (
  `id` varchar(32) NOT NULL,
  `create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `del_flag` int(1) DEFAULT NULL COMMENT '删除状态',
  `update_by` varchar(32) DEFAULT NULL COMMENT '修改人',
  `update_time` datetime DEFAULT NULL COMMENT '修改时间',
  `job_class_name` varchar(255) DEFAULT NULL COMMENT '任务类名',
  `cron_expression` varchar(255) DEFAULT NULL COMMENT 'cron表达式',
  `parameter` varchar(255) DEFAULT NULL COMMENT '参数',
  `description` varchar(255) DEFAULT NULL COMMENT '描述',
  `status` int(1) DEFAULT NULL COMMENT '状态 0正常 -1停止',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uniq_job_class_name` (`job_class_name`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

INSERT INTO `sys_quartz_job`
(`id`,`create_by`,`create_time`,`del_flag`,`update_by`,`update_time`,`job_class_name`,`cron_expression`,`parameter`,`description`,`status`)VALUES
('df26ecacf0f75d219d746750fe84bbee', NULL, NULL, '0', 'admin', '2020-05-02 15:40:35', 'org.jeecg.modules.quartz.job.SampleParamJob', '0/1 * * * * ?', 'scott', '带参测试 后台将每隔1秒执行输出日志', '-1');
public interface Job {
    void execute(String paramsJson);
}
@Component
public class ScheduleUtil {
    private static final Logger logger = LoggerFactory.getLogger(ScheduleUtil.class);

    private static ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    private static Map<String, ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();

    static {
        threadPoolTaskScheduler.initialize();
        logger.info("init threadPoolTaskScheduler");
    }

    private void start(SysTaskJob task) {
        String cronExpression = task.getCronExpression();
        String jobClassName = task.getJobClassName();
        String parameter = task.getParameter();
        ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.schedule(() -> {
            try {
                executeByClassName(jobClassName, parameter);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, (TriggerContext triggerContext) -> {
            if ("".equals(cronExpression) || cronExpression == null)
                return null;
            CronTrigger trigger = new CronTrigger(cronExpression);
            Date nextExecDate = trigger.nextExecutionTime(triggerContext);
            return nextExecDate;
        });
        scheduledFutureMap.put(task.getId(), scheduledFuture);
        logger.info("start timed task id=" + task.getId());
    }

    public void start(List<SysTaskJob> list) {
        List<String> ids = list.stream().map(SysTaskJob::getId).collect(Collectors.toList());
        Map<String, ScheduledFuture<?>> map = this.filterMapKeyNotInIds(ids);
        this.cancle(map);
        for (SysTaskJob sysTaskJob : list) {
            if (scheduledFutureMap.get(sysTaskJob.getId()) == null) {
                this.start(sysTaskJob);
            }
        }
    }


    private void cancle(Map<String, ScheduledFuture<?>> map) {
        for (Map.Entry<String, ScheduledFuture<?>> entry : map.entrySet()) {
            ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(entry.getKey());
            if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
                scheduledFuture.cancel(false);
            }
            scheduledFutureMap.remove(entry.getKey());
            logger.info("cancel timed task id=" + entry.getKey());
        }
    }

    // 利用反射获取需要执行的方法
    private void executeByClassName(String className, String parameter) throws Exception {
        Class<?> clazz = Class.forName(className);
        Job entity = (Job) clazz.newInstance();
        entity.execute(parameter);
    }

    private Map<String, ScheduledFuture<?>> filterMapKeyNotInIds(List<String> ids) {
        return scheduledFutureMap.entrySet().stream().filter(e -> !ids.contains(e.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
}
public class SoutTask implements Job {

    @Override
    public void execute(String paramsJson) {
        if (StringUtils.isNotEmpty(paramsJson)) {
            System.out.println(paramsJson);
        } else {
            System.out.println("no params");
        }
    }
}
@Component
public class SysTaskJobFacadeImpl {
    private static final Logger logger = LoggerFactory.getLogger(SysTaskJobFacadeImpl.class);
    @Autowired
    private SysTaskJobDAO sysTaskJobDAO;

    @Autowired
    private ScheduleUtil scheduleUtil;

    // 执行任务
//    @Scheduled(cron = "0 0/1 *  * * ? ")//每1分执行一次
    @Scheduled(cron = "0/10 * * * * ? ")//每10秒执行一次
    public void execute() {
        List<SysTaskJob> taskJobList = sysTaskJobDAO.listTaskJob();
        logger.info("flush timed task");
        scheduleUtil.start(taskJobList);
    }

}

1,建表   与jeecgboot中的表一致。

2,Job 接口   所有需要做定时执行的任务都需要 implements 该接口。做扩展只需要新建一个类,在数据库中插入一条数据即可。

3,ScheduleUtil 工具类 启动关闭定时任务

4,SoutTask 为测试类,implements Job 接口并实现 execute 方法,可以在 execute 方法中调用需要定时执行的方法即可。

5,调用   这里用了另一个定时任务定时获取数据库任务,这样当定时任务关闭时,可以自动停止定时任务。如果不考虑这些因素,也可以不要这个定时任务在初始化时,启动即可。

此处省略了 entity 实体类以及 dao 查询类

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值