架构师成长记_第三周_07_2020.11.08

文章目录

设置定时任务

自动生成Cron表达式链接工具

编写定时任务配置

package com.beyond.config;


import com.beyond.utils.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class OrderJob {

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

开启定时任务

架构师成长记_第三周_07_2020.11.08

效果展示

架构师成长记_第三周_07_2020.11.08

设置订单超时

编写超时配置并开启 OrderJob.java

package com.beyond.config;


import com.beyond.service.OrderService;
import com.beyond.utils.DateUtil;
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;

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

编写完善 orderService

 /**
     * 关闭超时未支付的订单
     */
    public void closeOrder();

编写完善 orderServiceImpl

@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){
                // 超过一天, 关闭订单
                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. 会有时间差, 会导致程序不严谨.
    比如: 10:20 下单, 11:00 检查不足一小时, 12:00 检查, 超过了1小时多余20分钟

  2. 不支持集群
    单机没毛病, 使用集群后, 就会有多个定时任务
    解决方案: 只使用一台计算机节点, 单独用来运行所有的定时任务

  3. 最大的弊端
    会对数据库全表搜索, 极其影响数据库性能,
    因为我们写的是 select * from order where orderStatus = 10 ;

所以, 这样的定时任务只是适用于小型轻量级项目, 传统项目.

后续会涉及到消息队列 : MQ -> RabbitMQ, RocketMQ, Kafka, ZeroMQ…
即启动 延时任务(队列)

上一篇:时间字符串和Date之前的转换


下一篇:hutool的时间工具类