java 通过Cron表达式实现自定义定时发布任务

项目中设置表达式的界面

代码:

import com.ruoyi.common.utils.DateUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
@EnableScheduling
public class SchedulerExampleService {

    @Autowired
    private  TGcglXsxcPlanMapper tGcglXsxcPlanMapper;

    private Scheduler scheduler;
    // 记录已调度任务的ID
    private Set<String> scheduledJobIds = new HashSet<>();

    public SchedulerExampleService() throws SchedulerException {
        scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
    }

    /*可以不用定时任务,启动项目时直接调用方法,这里需要查询可执行的任务数据*/
    @Scheduled(cron = "0 */1 * * * ?") // 每分钟执行一次可以实现自定义到秒级
    public void checkForUpdates() throws SchedulerException, ParseException {
        executeTask();
    }

    public  void executeTask() throws SchedulerException, ParseException {
        List<TGcglXsxcPlan> tGcglXsxcPlanList = tGcglXsxcPlanMapper.selectTGcglXsxcPlanListByRwTypes();
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");

        for (TGcglXsxcPlan item : tGcglXsxcPlanList) {
            String jobId = item.getId();
            String groupName = "group1";

            if (scheduledJobIds.contains(jobId)) {
                continue; // 如果任务已经调度,跳过
            }

            JobKey jobKey = new JobKey(jobId, groupName);
            if (scheduler.checkExists(jobKey)) {
                scheduler.deleteJob(jobKey);
            }


            JobDetail jobDetail = JobBuilder.newJob(MyJobService.class)
                    .usingJobData("dataName", item.getId())
                    .withIdentity(jobId, groupName)
                    .build();

            Trigger trigger = null;
            if (null!=item.getZxstart()&&null!=item.getZxend()){
                Long now = System.currentTimeMillis();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date etime = sdf.parse(item.getZxend());
                Long time = etime.getTime();
                if (null!=item.getCron()&&time>now){
                    System.out.println(item.getCron());
                    try {

                        // 计算任务的开始时间
                        long startTime = DateUtils.parseDate(item.getZxstart(), "yyyy-MM-dd").getTime();
                        if (now > startTime) {
                            startTime = now + 1000; // 如果当前时间超过开始时间,设置为1秒后启动,防止立即执行
                        }
                        Date date = new Date(startTime);

                        trigger = TriggerBuilder.newTrigger()
                                .withIdentity(jobId, groupName)
                                .withSchedule(CronScheduleBuilder.cronSchedule(item.getCron())
                                        .inTimeZone(timeZone))
                                .startAt(new Date(startTime))
                                .endAt(DateBuilder.translateTime(DateUtils.parseDate(item.getZxend(), "yyyy-MM-dd"), timeZone, timeZone))
                                .build();

                        //.startAt(DateBuilder.translateTime(DateUtils.parseDate(item.getZxstart(),"yyyy-MM-dd"), timeZone, timeZone))

                    } catch (ParseException e) {
                        e.printStackTrace();
                        continue; // 如果发生异常,跳过当前任务的处理
                    }

                    scheduler.scheduleJob(jobDetail, trigger);
                    scheduledJobIds.add(jobId); // 记录已调度任务的ID
                    System.out.println(scheduler);
                }
            }
        }
    }
}
package com.ruoyi.project.gcgl.xsxc.service;


import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.message.MovingMessageUtil;
import com.ruoyi.project.gcgl.saqgl.service.TGcglSaqglScheduleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.quartz.CronExpression;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class MyJobService implements Job {

    private static TGcglXsxcPlanService tGcglXsxcPlanService;

    private static TGcglSaqglScheduleService scheduleService;

    private static TPubSysUserService sysUserService;

    private static TGcglXsxcHistoryRecordService historyRecordService;

    private static TGcglOrganService organService;

    @Autowired
    public void setTGcglXsxcPlanService(TGcglXsxcPlanService tGcglXsxcPlanService) {
        MyJobService.tGcglXsxcPlanService = tGcglXsxcPlanService;
    }

    @Autowired
    public void setTGcglSaqglScheduleService(TGcglSaqglScheduleService scheduleService) {
        MyJobService.scheduleService = scheduleService;
    }

    @Autowired
    public void setTPubSysUserService(TPubSysUserService sysUserService) {
        MyJobService.sysUserService = sysUserService;
    }

    @Autowired
    public void setTGcglXsxcHistoryRecordService(TGcglXsxcHistoryRecordService historyRecordService) {
        MyJobService.historyRecordService = historyRecordService;
    }

    @Autowired
    public void setTGcglOrganService(TGcglOrganService organService) {
        MyJobService.organService = organService;
    }


    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // 执行具体的业务逻辑
        // 这里可以读取数据库中的任务数据,查询对应的人员,下发待办信息
        // 获取传递给任务的数据标识符
        String dataId = context.getJobDetail().getJobDataMap().getString("dataName");
        TGcglXsxcHistoryRecord historyRecord = new TGcglXsxcHistoryRecord();
        historyRecord.setPlanId(dataId);
//        historyRecord.setPatrolTime(DateUtils.getNowDate());

        TGcglXsxcPlan plan = tGcglXsxcPlanService.selectTGcglXsxcPlanById(dataId);
        CronExpression expression;
        try {
            expression = new CronExpression(plan.getCron());
        } catch (ParseException e) {
            log.error("任务ID为:{} ,Cron表达式解析失败! err -> {}", dataId, e.getMessage());
            throw new RuntimeException(e);
        }
        //下一次执行时间
        Date nextTriggerTime = expression.getNextValidTimeAfter(new Date());
        //最后触发时间
        Date lastTriggerTime = getLastTriggerTime(expression, nextTriggerTime);
        if (ObjectUtils.isNotEmpty(lastTriggerTime)){
            historyRecord.setStartTime(lastTriggerTime);
            historyRecord.setEndTime(nextTriggerTime);
            List<TGcglXsxcHistoryRecord> recordList = historyRecordService.selectTGcglXsxcHistoryRecordList(historyRecord);
            //查询当前任务当前时间的记录是否存在,如果存在则不生成
            if (CollectionUtils.isEmpty(recordList)) {
                //插入待办信息
                processBusinessLogic(plan);
            }
        }
    }


    /**
     * 插入待办信息 和 历史记录
     *
     * @param plan
     */
    private void processBusinessLogic(TGcglXsxcPlan plan) {
        //业务代码。。。
    }

    public static Date getLastTriggerTime(CronExpression cron, Date validTimeAfter) {
        long currTime = System.currentTimeMillis();
        Date validTimeAfter1 = cron.getNextValidTimeAfter(validTimeAfter);
        //计算出下下次触发  与下次触发的 差值
        long diff = validTimeAfter1.getTime() - validTimeAfter.getTime();
        //当前时间 减去两次差值
        long startCalcTime = currTime - diff * 2;
        Date date = new Date(startCalcTime);
        //当前时间date
        Date currTimeDate = new Date();
        //应该触发的时间
        Date previousFireTime = null;
        Date nextFireTime = cron.getNextValidTimeAfter(date);
        int i = 0;
        // 迭代计算上一次执行时间
        while (nextFireTime != null && nextFireTime.before(currTimeDate)) {
            previousFireTime = nextFireTime;
            nextFireTime = cron.getNextValidTimeAfter(nextFireTime);
            if (i++ >= 100) {
                return null;
            }
        }
        return previousFireTime;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值