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

相关推荐
阿丰资源9 小时前
基于SpringBoot的在线视频教育平台的设计与实现(附源码+数据库+文档,一键运行)
数据库·spring boot·后端
IT_陈寒9 小时前
我竟然被JavaScript的隐式类型转换坑了三天!
前端·人工智能·后端
Reart9 小时前
从0解构tinyWeb项目--(Day:9)
后端·架构·github
小码哥_常9 小时前
Java后端定时任务“三剑客”大比拼,选对不选贵!
后端
oldking呐呐9 小时前
MySQL从入门到入土 -- 2.数据库基础
后端·mysql
用户860821135659 小时前
从JVM到Spring Boot:一文搞懂胖Jar中的类加载机制
后端
小兵张健9 小时前
30天减20斤挑战:少一斤发100红包(2)
后端·程序员·全栈
汤姆Tom9 小时前
从 0 到 1 开发项目?你是否也是这样开始?先有再优化一步一步带你了解架构设计
前端·后端·架构
muskk13 小时前
一个文件,9万星:Karpathy 用 4 条规则治好了 AI 写代码的"坏毛病"
前端·后端
xlecho14 小时前
从单一语言到全域全栈,AI凭全能实力,淘汰旧时代语言工程师
人工智能·后端·开源