当前位置: 首页 > article >正文

java定时服务

定时服务执行时只能查询当前数据库中已有的数据,新增的数据不能即时加入到定时任务中

为解决此问题,双重任务嵌套

package org.springblade.demo.job;

import org.apache.commons.lang3.StringUtils;
import org.springblade.demo.entity.PatrolTask;
import org.springblade.demo.mapper.PatrolTaskMapper;
import org.springblade.demo.util.ScheduledUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.TriggerTask;
import org.springframework.scheduling.support.CronTrigger;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;

/**
 * @author jbei
 * @since 2022-06-07 15:50
 */
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
    //笔者这里配合数据库来实现动态添加。方便查询数据库这里使用JdbcTemplate

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    PatrolTaskMapper patrolTaskMapper;

    private ScheduledTaskRegistrar taskRegistrar;

    private Set<ScheduledFuture<?>> scheduledFutures = null;

    private Map<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<>();

    private List<String> idList = new ArrayList<>();

    private String rentNames = "";

    /**
     * 这个方法在Spring初始化的时候会帮我们执行,这里也会拉取数据库内需要执行的任务,进行添加到定时器里。
     *
     * @param scheduledTaskRegistrar
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        List<TriggerTask> list = new ArrayList<>();
        //循环添加任务
        TriggerTask triggerTask = new TriggerTask(() -> {
            //定时任务
            //TODO  每分钟获取所有计划任务的情况
            toPushPatrolTask(taskRegistrar);
        }, triggerContext -> {
            return new CronTrigger("*/30 * * * * ?").nextExecutionTime(triggerContext);
        });
        list.add(triggerTask);
        //将任务列表注册到定时器
        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
        scheduledTaskRegistrar.setTriggerTasksList(list);
        this.taskRegistrar = scheduledTaskRegistrar;

    }

    private void toPushPatrolTask(ScheduledTaskRegistrar scheduledTaskRegistrar) {

        //查询出来当前数据库中存储的所有有效的任务
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from asset_patrol  where is_deleted=0 and cron IS not NULL and cron !=''");
        Map<String, String> keyCronMap = new HashMap();
        //循环添加任务
        maps.forEach(t -> {
            //TODO 去重
            String patrolId = t.get("id").toString();
            String cron = t.get("cron").toString();
            if (!idList.contains(patrolId + cron)) {
                idList.add(patrolId + cron);
                TriggerTask triggerTask = new TriggerTask(() -> {
                    addPatrolTask(t);
                }, triggerContext -> {
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                });
                //将任务列表注册到定时器
                addTask(patrolId, triggerTask);
            }
        });

    }

    private Runnable getRunnable(Map<String, Object> map) {

        return new Runnable() {
            @Override
            public void run() {
                addPatrolTask(map);
                try {
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
    }


    private Trigger getTrigger(String cron) {
        return new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        };
    }

    /**
     * 根据传入的巡查计划,新增巡查任务
     *
     * @param time
     */
    public LocalDateTime parseStringToDateTime(String time, String format) {
        time=time.substring(0,time.length()-2);
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(time, df);
    }
    private void addPatrolTask(Map<String, Object> t) {
        String assetids = t.get("scope_ids") == null ? "" : t.get("scope_ids").toString();
        assetids = assetids.substring(0, assetids.length() - 1);
        assetids = assetids.replace(";", "','");
        List<String> rentNamesList = jdbcTemplate.queryForList("select rent_name from asset_contract  where is_deleted=0 and now()>rent_start_date and now() < rent_end_date and id in" +
                " (select contract_id from asset_contract_assets where asset_id in ('" + assetids + "'))", String.class);
        rentNames = StringUtils.join(rentNamesList, ";");
        System.out.println("定时任务:" + t.get("cron").toString() + "添加任务,时间" + LocalDateTime.now().toLocalTime());
        PatrolTask patrolTask = new PatrolTask();
        // 设置任务对应的巡查计划
        patrolTask.setPatrolId(((Number) t.get("id")).longValue());
        patrolTask.setPatrolPersonid(t.get("patrol_personid") != null ? t.get("patrol_personid").toString() : "");
        // 设置任务状态是未领取
        patrolTask.setStatus(0);
        patrolTask.setCycle((Integer)t.get("cycle"));
        // 设置巡查时间
        patrolTask.setPatrolDate(LocalDateTime.now());
        patrolTask.setCreateTime(new Date());
        patrolTask.setCreateDept(((Number) t.get("create_dept")).longValue());
        patrolTask.setRemark(null == t.get("remark") ? "" : t.get("remark").toString());
        patrolTask.setRentNames(rentNames);
        // 设置巡查生效时间
        // TODO
        if (t.get("effective_date")!=null){
            patrolTask.setEffectiveDate(parseStringToDateTime(t.get("effective_date").toString(),"yyyy-MM-dd HH:mm:ss"));
        }

        patrolTask.setPlanName(null == t.get("plan_name") ? "" : t.get("plan_name").toString());
        patrolTask.setPatrolPersonname(null == t.get("patrol_personname") ? "" : t.get("patrol_personname").toString());
        patrolTask.setScope(null == t.get("scope") ? "" : t.get("scope").toString());
        patrolTask.setScopeIds(null == t.get("scope_ids") ? "" : t.get("scope_ids").toString());
        patrolTask.setAssetRoadArea(null == t.get("asset_road_area") ? "" : t.get("asset_road_area").toString());
        int a = patrolTaskMapper.insert(patrolTask);
    }


    /**
     * 添加任务
     *
     * @param taskId
     * @param triggerTask
     */
    public void addTask(String taskId, TriggerTask triggerTask) {
        //如果定时任务id已存在,则取消原定时器,从新创建新定时器,这里也是个更新定时任务的过程。
        if (taskFutures.containsKey(taskId)) {
            System.out.println("the taskId[" + taskId + "]  取消,重新添加");
            cancelTriggerTask(taskId);
        }
        TaskScheduler scheduler = taskRegistrar.getScheduler();
        ScheduledFuture<?> future = scheduler.schedule(triggerTask.getRunnable(), triggerTask.getTrigger());
        getScheduledFutures().add(future);
        taskFutures.put(taskId, future);
    }

    /**
     * 获取任务列表
     */
    private Set<ScheduledFuture<?>> getScheduledFutures() {
        if (scheduledFutures == null) {
            try {
                scheduledFutures = (Set<ScheduledFuture<?>>) ScheduledUtils.getProperty(taskRegistrar, "scheduledTasks");
            } catch (NoSuchFieldException e) {
                throw new SchedulingException("not found scheduledFutures field.");
            }
        }
        return scheduledFutures;
    }

    /**
     * 取消任务
     */
    public void cancelTriggerTask(String taskId) {
        ScheduledFuture<?> future = taskFutures.get(taskId);
        if (future != null) {
            future.cancel(true);
        }
        taskFutures.remove(taskId);
        getScheduledFutures().remove(future);
    }
}


http://www.kler.cn/a/284943.html

相关文章:

  • C指针创建三维数组
  • mapreduce 将数据清洗后保存到 hbase
  • 【Java学习】电脑基础操作和编程环境配置
  • 数据库管理-第260期 业务向前,数据库向后(20241111)
  • Unity 网格模型及优化
  • 关于Django 模型字段 `choices`自定义数据类型的枚举——补充
  • Python学习日志(1)——安装
  • Linux-arm64中断现场保护详解
  • MySQL 集群技术全攻略:从搭建到优化(上)
  • 分类模型评估指标——准确率、精准率、召回率、F1、ROC曲线、AUC曲线
  • 快递盒检测检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]
  • RAG 向量数据库:掌握 Elasticsearch 作为向量数据库的终极指南
  • 【Python零基础】文件使用和异常处理
  • Vue(四) 组件、单文件组件、非单文件组件,重要的内置关系
  • 【计组 | Cache原理】讲透Cache的所有概念与题型方法
  • 大模型好书案例——《BERT基础教程:Transformer大模型实战》(附PDF)
  • LuaJit分析(一)LuaJit交叉编译
  • TCP的连接与断开
  • java基础开发-xstream解析xml
  • 去中心化(Decentralization)
  • leetcode1514 最大概率路径(Bellman-ford算法详解)
  • 栈算法【基于顺序表】
  • centos 系统yum 安装 mariadb
  • UML类图中的组合关系
  • Vue3 + Axios双Token刷新解决方案
  • MySQL——多表操作(四)子查询(1)带 IN 关键字的子查询