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

相关推荐
打工仔折腾 AI20 分钟前
从 Demo 到生产级 Agent:8 个关键设计机制与 Python 实现拆解
java·jvm·人工智能·后端·python·langchain·ai agent 实战
架构技术专栏42 分钟前
交叉熵:AI 怎样给概率预测打分
后端
IT_陈寒2 小时前
SpringBoot自动配置坑了我一把,原来是这样绕过去的
前端·人工智能·后端
要努力啊4693 小时前
用 Codex 加速 Java 开发:从代码生成到测试覆盖的完整实战
后端
dora3 小时前
LangChain4j 新手入门实战教程(Java版)
后端·langchain·agent
蜗牛互联网3 小时前
MongoDB Atlas Agent Engine之后,如何用版本门禁防止陈旧写入
java·数据库·人工智能·后端·mongodb
付威20233 小时前
Rust 生命周期:为什么要有它,实际代码里到底怎么用?
后端
海岳云舟3 小时前
spring使用kafka的三种方式(listener、container、stream)
后端
谢亮_vipxieliang5 小时前
Spring Boot 自动配置原理:从 @SpringBootApplication 到自定义 Starter
java·spring boot·后端
我的div丢了肿么办5 小时前
go语言中的空接口和类型断言
后端·go