# 定时任务

支付流程完成之后,其实还有好多用户会不支付,那么数据库中就会存在很多未支付的订单(10 状态),就可以使用定时任务去关闭这些超时的订单.

这里使用 spring boot 自带的定时任务

package cn.mrcode.foodiedev.config;

import cn.mrcode.foodiedev.common.util.DateUtil;
import cn.mrcode.foodiedev.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class OrderJob {

    @Autowired
    private OrderService orderService;

    /**
     * 使用定时任务关闭超期未支付订单,会存在的弊端:
     * 1. 会有时间差,程序不严谨
     * 10:39 下单,11:00 检查不足 1 小时,12:00 检查,超过 1 小时多余 39 分钟
     * 2. 不支持集群
     * 单机没毛病,使用集群后,就会有多个定时任务
     * 解决方案:只使用一台计算机节点,单独用来运行所有的定时任务
     * 3. 会对数据库全表搜索,及其影响数据库性能:select * from order where orderStatus = 10;
     * 定时任务,仅仅只适用于小型轻量级项目,传统项目
     * <p>
     * 后续课程会涉及到消息队列:MQ-> RabbitMQ, RocketMQ, Kafka, ZeroMQ...
     * 延时任务(队列)
     * 10:12 分下单的,未付款(10)状态,11:12 分检查,如果当前状态还是 10,则直接关闭订单即可
     */

//    @Scheduled(cron = "0/3 * * * * ?")
//    @Scheduled(cron = "0 0 0/1 * * ?")
    public void autoCloseOrder() {
        orderService.closeOrder();
        System.out.println("执行定时任务,当前时间为:"
                + DateUtil.getCurrentDateString(DateUtil.DATETIME_PATTERN));
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

service


    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void closeOrder() {

        // 查询所有未付款订单,判断时间是否超时(1天),超时则关闭交易
        OrderStatus queryOrder = new OrderStatus();
        queryOrder.setOrderStatus(OrderStatusEnum.WAIT_PAY.type);
        List<OrderStatus> list = orderStatusMapper.select(queryOrder);
        for (OrderStatus os : list) {
            // 获得订单创建时间
            Date createdTime = os.getCreatedTime();
            // 和当前时间进行对比
            int days = DateUtil.daysBetween(createdTime, new Date());
            if (days >= 1) {
                // 超过1天,关闭订单
                doCloseOrder(os.getOrderId());
            }
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    void doCloseOrder(String orderId) {
        OrderStatus close = new OrderStatus();
        close.setOrderId(orderId);
        close.setOrderStatus(OrderStatusEnum.CLOSE.type);
        close.setCloseTime(new Date());
        orderStatusMapper.updateByPrimaryKeySelective(close);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29