SpringBoot 中实现订单30分钟自动取消

在涉及到支付的业务时,通常需要实现一个功能:如果用户在生成订单的一定时间内未完成支付,系统将自动取消订单。本文将基于Spring Boot框架实现订单30分钟内未支付自动取消的几种方案,并提供实例代码。

方案一:定时任务

利用@Scheduled注解,我们可以轻松实现定时任务,周期性扫描订单记录,检查未支付的订单,如果有满足三十分钟则进行关闭。

ini 复制代码
@Component
public class OrderSchedule {
    @Autowired
    private OrderService orderService;

    @Scheduled(cron = "0 0/1 * * * ?")
    public void cancelUnpaidOrders() {
        LocalDateTime now = LocalDateTime.now();
        List<Integer> idList = new ArrayList<Integer>();
        List<OrderEntity> orderList = orderService.getOrderList();
        orderList.forEach(order -> {
            if (order.getWhenCreated().plusMinutes(30).isBefore(now)) {
                idList.add(order.getId());
          }
        });
        orderService.cancelOrderList(idList);
        }
}

方案二:延迟队列

使用消息队列的延迟队列,当订单生成时将订单ID推送到延迟队列,设置30分钟后过期,过期后消费该消息,判断订单状态,如果未支付则取消订单。

typescript 复制代码
@Service
public class OrderService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void createOrder(Order order) {
        // 保存数据库
        saveOrder(order);

        // 将订单ID推送至延迟队列
        rabbitTemplate.convertAndSend("orderDelayExchange", "orderDelayKey", order.getId(), message -> {
            message.getMessageProperties().setDelay(30 * 60 * 1000); // 设置延迟时间
            return message;
        });
    }
}

@Component
public class OrderDelayConsumer {

    @Autowired
    private OrderService orderService;

    @RabbitHandler
    @RabbitListener(queues = "orderDelayQueue")
    public void cancelOrder(String orderId) {
        // 取消订单
        orderService.cancelOrder(orderId);
    }
}

方案三:redis过期事件

使用redis的key过期事件,当订单创建时在Redis中存储一个key,设置30分钟过期,key过期时通过redis的过期事件通知功能触发订单取消。

scss 复制代码
@Service
public class OrderService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void createOrder(Order order) {
        // 保存订单至数据库
        saveOrder(order);

        // 在redis中存储一个key,设置30分钟过期
        redisTemplate.opsForValue().set("order:" + order.getId(), order.getId(), 30, TimeUnit.MINUTES);
    }

    // 当key过期时,redis会自动调用该方法(需要配置redis的过期事件通知)
    public void onOrderKeyExpired(String orderId) {
        cancelOrder(orderId);
    }
}

注:redis的key过期通知是一种典型的发布-订阅模式。在redis中,我们可以订阅到某些特定的事件。key过期事件就是其中之一。但想要使用这个功能,需要redis服务器开启相关配置。具体如何配置会在后期的文章里分享给大家。

最后总结:

三种方案都可以实现订单在30分钟内未支付则自动取消的需求。根据实际业务需求、系统负载和其他因素,可以选择最适合自己系统的实现方案。每种方案都有其优缺点,需要根据具体情况权衡。

相关推荐
一只叫煤球的猫3 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9653 小时前
tcp/ip 中的多路复用
后端
bobz9654 小时前
tls ingress 简单记录
后端
你的人类朋友5 小时前
什么是OpenSSL
后端·安全·程序员
bobz9655 小时前
mcp 直接操作浏览器
后端
前端小张同学7 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook8 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康8 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在8 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net
文心快码BaiduComate9 小时前
文心快码入选2025服贸会“数智影响力”先锋案例
前端·后端·程序员