jfinal quartz 定时器 后台维护

业务场景,以下单为例,如果订单在24小时内未付款,则定时器执行,修改订单未失效

1.ProjectConfig 启动时开启定时功能

public void onStart() {
//开启
        QuartzManager qm = new QuartzManager();
        qm.initJob();
    }

    // 系统关闭之前回调
    @Override
 public void onStop() {
 //项目暂停时 关闭
        QuartzManager qm = new QuartzManager();
        qm.shutdown();
    }

2.QuartzManager 工具类

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.List;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;


/**
 * @Author: Timelk
 * @Date: 2021-08-10 9:33
 */
public class QuartzManager {

    private Logger log = LogManager.getLogger(QuartzManager.class);

    private Scheduler scheduler = null;

    public QuartzManager() {
        try {
            scheduler = new StdSchedulerFactory().getScheduler();
            //log.info("初始化调度器 ");
        } catch (SchedulerException ex) {
            log.error("初始化调度器=> [失败]:" + ex.getLocalizedMessage());
        }
    }

    //初始化启动任务 这里订单在创建时,会在表中创建一条执行失效的记录,但项目如果关闭,定时就会暂停,每次项目启动前需要在这执行定时任务
    public void initJob() {
        List<BusOrderTimeout> jobs = BusOrderTimeout.dao.template("orderTimeout.find", Kv.by("is_enabled", "2")).find();
        for (BusOrderTimeout job : jobs) {
            if ("2".equals(job.getStr("is_enabled"))) {
                String className = job.getStr("clazz");
                String name = job.getStr("name");
                String group = job.getStr("group");
                String cronExpression = job.getStr("cron_expression");
                this.addJob(name, group, className, cronExpression);
            }
        }
        this.start();

    }

    //添加任务 
    public void addJob(String name, String group, String className, String cronExpression) {
        Class<? extends Job> jobClazz = null;
        try {
            jobClazz = Class.forName(className).asSubclass(Job.class);
            // 构造任务
            JobDetail job = newJob(jobClazz).withIdentity(name, group).build();
            //定时器中存入id
            job.getJobDataMap().put("id", name);
            // 构造任务触发器
            Trigger trg = newTrigger().withIdentity(name, group).withSchedule(cronSchedule(cronExpression)).build();
            // 将作业添加到调度器
            scheduler.scheduleJob(job, trg);
            log.info("创建作业=> [作业名称:" + name + " 作业组:" + group + "id: " + name + "] ");
        } catch (SchedulerException | ClassNotFoundException e) {
            e.printStackTrace();
            log.error("创建作业=> [作业名称:" + name + " 作业组:" + group + "id: " + name + "]=> [失败]");
        }
    }

    //移除任务
    public void removeJob(String name, String group) {
        try {
            TriggerKey tk = TriggerKey.triggerKey(name, group);
            scheduler.pauseTrigger(tk);// 停止触发器
            scheduler.unscheduleJob(tk);// 移除触发器
            JobKey jobKey = JobKey.jobKey(name, group);
            scheduler.deleteJob(jobKey);// 删除作业
            log.info("删除作业=> [作业名称:" + name + " 作业组:" + group + "] ");
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("删除作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]");
        }
    }

    public void start() {
        try {
            scheduler.start();
            //log.info("启动调度器 ");
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("启动调度器=> [失败]");
        }
    }

    public void shutdown() {
        try {
            scheduler.shutdown();
            //log.info("停止调度器 ");
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("停止调度器=> [失败]");
        }
    }


}

3.下单&取消订单

public void create() {
        Db.tx(() -> {
            try {
                String format = DateUtil.format(new Date(), "yyyyMMddHHmmss");
                String numbers = RandomUtil.randomNumbers(5);
                String liushui = format + numbers;
                BusOrder target = new BusOrder();
                target.setId(UuidKit.getUUIDNoMinus());
                target.setCreateTime(DateUtil.now());
                target.setOrderId(liushui);
                target.setPayMethod(get("pay_method"));
                target.setUserId(user.getId());
                target.setNote(get("note"));
                target.setActualPrice(get("actual_price"));
                target.save();
                //加入调度 动态增加一个定时器
                OrderJob.saveOrderJob(target, "订单失效定时创建");
                rs("下单成功")
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return true;
        });
    }
/**
     * 取消订单
     */
    public void delete() {
        String id = get("id");
        Db.tx(() -> {
            try {
                BusOrder target = BusOrder.dao.template("order.find",
                                Kv.by("id", id))
                        .findFirst();
                if (target != null) {
                    target.setCancelTime(DateUtil.now());
                    target.setState("0");//改失效
                    target.update();
                    //删除调度
                    OrderJob.deleteOrderJob(target);
                }
                rs(CodeKit.DELETE_SUCCESS_MESSAGE);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return true;
        });
    }

4. 定时器 相关逻辑

package com.huayueye.t.job.task;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.huayueye.b.model.BusOrder;
import com.huayueye.b.model.BusOrderTimeout;
import com.huayueye.t.job.QuartzManager;
import com.jfinal.kit.Kv;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
/**
 * @Author: 订单超时改失效
 * @Date: 2021-08-10 9:35
 */
public class OrderJob implements Job {

    @Override //定时执行进入此方法
    public void execute(JobExecutionContext context) throws JobExecutionException {
        String id = context.getMergedJobDataMap().getString("id");
        BusOrder order = BusOrder.dao.template("order.find", Kv.by("id", id)).findFirst();
        try {
            if (order.getState().equals("1")) {
                order.setState("0");
                order.setCancelTime(DateUtil.now());
                order.update();
                deleteOrderJob(order);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        /*System.out.println("订单超时查询");
        List<BusOrder> list = BusOrder.dao.template("order.find", Kv.by("state", "1")).find();
        List<BusOrder> noOrders = new ArrayList<>();
        if (list.size()>0){
            for (BusOrder order:list){
                String createTime = order.getCreateTime();
                Date create_date = Convert.toDate(createTime);
                Date now = Convert.toDate(DateUtil.now());
                long l = DateUtil.betweenDay(create_date, now, false);
                //超过一天
                if (l>0){
                    order.setState("0");
                    order.setCancelTime(DateUtil.now());
                    noOrders.add(order);
                }
            }
        }
        Db.batchUpdate(noOrders, noOrders.size());*/
    }

    //新建定时 订单失效 开启
    public static void saveOrderJob(BusOrder order, String group) {
        BusOrderTimeout orderTimeout = new BusOrderTimeout();
        orderTimeout.setCreateTime(DateUtil.now());
        orderTimeout.setName(order.getId());
        orderTimeout.setGroup(group);
        orderTimeout.setClazz("com.huayueye.t.job.task.OrderJob");
        //计算24小时的失效时间
        String createTime = order.getCreateTime();
        Date create_date = Convert.toDate(createTime);
        DateTime stime = DateUtil.offsetDay(create_date, 1);
        String formatDate = DateUtil.format(stime, "yyyy-MM-dd HH:mm:ss");
        //计算cron
        orderTimeout.setCronExpression(onlyOnce(formatDate));
        orderTimeout.save();
        QuartzManager qm = new QuartzManager();
        qm.addJob(orderTimeout.getName(), orderTimeout.getGroup(), orderTimeout.getClazz(), orderTimeout.getCronExpression());
    }
    
	//订单失效关闭
    public static void deleteOrderJob(BusOrder target) {
        BusOrderTimeout orderTimeout = BusOrderTimeout.dao.template("orderTimeout.find", Kv.by("name", target.getId()).set("is_enabled", "2")).findFirst();
        if (orderTimeout != null) {
            QuartzManager qm = new QuartzManager();
            qm.removeJob(orderTimeout.getName(), orderTimeout.getGroup());//定时删除
            orderTimeout.setIsEnabled("1");//关闭
            orderTimeout.update();
        }
    }


    /**
     * 仅一次
     *
     * @param dateStr 2022-03-31 09:51:05
     * @return
     */
    public static String onlyOnce(String dateStr) {
        LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy"));
        return cronStr;
    }
}

5.转cron 代码

链接: 转cron 代码

6.表结构

在这里插入图片描述

CREATE TABLE `bus_order_timeout`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'task name',
  `group` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '分组',
  `clazz` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'class name',
  `cron_expression` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'cron tab',
  `is_enabled` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '2' COMMENT 'is enable 2开1关',
  `create_time` varchar(19) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'create time',
  PRIMARY KEY (`id`) USING BTREE
) 

其余按自己逻辑来吧

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值