SpringBoot+RabbitMQ实现超时未支付订单自动取消,localhost:15672没有登录页面。

这篇具有很好参考价值的文章主要介绍了SpringBoot+RabbitMQ实现超时未支付订单自动取消,localhost:15672没有登录页面。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

安装RabbitMQ需要安装Erlang/OTP,并保持版本匹配。
RabbitMQ官网:RabbitMQ: One broker to queue them all | RabbitMQ
RabbitMQ与Erlang/OTP版本对照表:Erlang Version Requirements | RabbitMQ
Erlang官网下载:Downloads - Erlang/OTP

1.Windows上安装RabbitMQ前需要安装Erlang。(下载安装不做叙述,除了需要自定义安装目录外,按照默认安装即可。安装Erlang后配置一下环境变量,与配置jdk环境变量一致)

给大家一个我用的RabbitMQ版本是3.13.1
Erlang/OTP版本是26.0。需要自取即可。
下载地址:https://share.weiyun.com/dWR1pwh3
密码:3jcsqs

1.1 RabbitMQ常用命令 

管理员身份打开命令提示符。
1:cd C:\rabbitmq_server-3.13.1\sbin 到自己解压的文件路径的sbin目录下。
2:rabbitmq-service install 安装一下
3:rabbitmq-service start 启动
4:rabbitmq-service stop 停止

1.2 启动后如果没问题输入下面的url应该会出现一个登录的页面。

localhost:15672
用户名和密码都是guest

1.3 如果没有登录页面提示找不到的话按照以下操作应该就可以了。

输入命令rabbitmq-plugins list正常启动的服务应该是如下所示,E和e分别表示显性和隐性启动,如果没有E和e,这也就是你打不开localhost:15672的原因所在,可能性很大。
那么,就再输入rabbitmq-plugins enable rabbitmq_management基本就可以解决打不开的问题了。
使用rabbitmq实现取消超时未支付订单,java-rabbitmq,spring boot,rabbitmq

2.环境准备完后后,上代码。 

2.1 maven的pom文件。

        <!-- springboot集成rabbitMQ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

 2.2 yml文件配置。
 

# RabbitMQ
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    listener:
      simple:
        retry:
          initial-interval: 5000
          enabled: true
          max-attempts: 3
        default-requeue-rejected: false
        acknowledge-mode: auto

解释一下配置文件中的内容:
host: 127.0.0.1 这指定了 RabbitMQ 服务器的主机地址,127.0.0.1 表示本地主机,即运行 RabbitMQ 的计算机。

port: 5672 这是 RabbitMQ 服务器监听连接的端口号。默认情况下,RabbitMQ 使用 5672 端口。

username和password这是连接 RabbitMQ 服务器所需的用户名和密码。在默认情况下,RabbitMQ 的默认用户名和密码都是 guest。

virtual-host: / 虚拟主机的名称。RabbitMQ 允许将多个逻辑消息服务运行在单个物理主机上,每个逻辑服务都有自己的虚拟主机。/ 表示默认的虚拟主机器
listener: 这个部分定义了监听器配置。
simple: 这个监听器类型是简单的消息监听器。
retry:这个子部分定义了消息重试策略。
initial-interval: 5000:初始重试间隔,单位为毫秒。即在第一次重试失败后,将等待 5000 毫秒再次重试。
enabled: true:表示重试机制启用
max-attempts: 3:最大重试次数,即消息在被丢弃之前尝试重新传递的最大次数。
default-requeue-rejected: false:当消息被拒绝时,是否重新排队。这里设置为 false 表示不重新排队。
acknowledge-mode: auto 消息确认模式。在这里设置为 auto,表示消息处理后会自动确认,如果处理失败,则消息将会重传。

2.3 新建一个交换机配置类
 


import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

/**
 * <p>
 * 消息队列配置类
 * </p>
 *
 * @author Lch
 * @dateTime 2024/4/1 14:28
 */
@Configuration
public class OrderQueueConfig {
    /**
     * 普通交换机名称
     */
    private static final String ORDER_EXCHANGE = "normal_order_exchange";

    /**
     * 死信交换机名称
     */
    private static final String DEAD_EXCHANGE = "normal_dead_exchange";

    /**
     * 普通队列名称
     */
    private static final String ORDER_QUEUE = "normal_order_queue";

    /**
     * 延迟队列名称
     */
    private static final String DELAY_QUEUE = "normal_delay_queue";


    /**
     * 声名普通交换机
     * @return direct(默认)交换机
     */
    @Bean("orderNormalExchange")
    public DirectExchange orderExchange() {
        return new DirectExchange(ORDER_EXCHANGE);
    }

    /**
     * 声名死信交换机
     * @return direct(默认)交换机
     */
    @Bean("deadDelayExchange")
    public DirectExchange deadExchange() {
        return new DirectExchange(DEAD_EXCHANGE);
    }

    /**
     * 声名延迟队列
     * @return direct(默认)交换机
     */
    @Bean("delayDelayQueue")
    public Queue delayQueue() {
        return QueueBuilder.durable(DELAY_QUEUE).build();
    }

    /**
     * 声名普通队列并与死信队列进行绑定
     * @return 名为ORDER_QUEUE的持久化队列(Durable Queue)
     *
     * x-dead-letter-exchange:设置了死信交换机,即消息过期后将会发送到哪个交换机。在这里
     * 设置为 DEAD_EXCHANGE,即名为normal_dead_exchange的交换机。
     * x-dead-letter-routing-key:设置了死信的路由键,即消息过期后发送到死信交换机后的路由键。在这里,设置为 expire
     * 通过这些设置,配置了一个普通队列,并且定义了当队列中的消息过期后的行为,即发送到指定的死信交换机并且指定了死信的路由键。
     * 当队列中的消息过期后,会被标记为死信并发送到名为 DEAD_EXCHANGE(normal_dead_exchange)的交换机中,并且使用"expire"作为路由键。
     * 所以消息过期后,将消息标注为死信,然后根据此方法配置的死信交换机和路由键进行重新路由到 normal_order_queue 队列中
     * 通过 @RabbitListener(queues = {"normal_delay_queue"}) 可以监听到 DEAD_EXCHANGE(normal_order_queue)的消息。
     */
    @Bean("orderNormalDelayQueue")
    public Queue orderQueue() {
        HashMap<String, Object> param = new HashMap<>();
        // 设置死信交换机
        param.put("x-dead-letter-exchange", DEAD_EXCHANGE);
        // 设置死信routingKey
        param.put("x-dead-letter-routing-key", "expire");
        return QueueBuilder.durable(ORDER_QUEUE).withArguments(param).build();
    }

    /**
     * 普通队列与交换机绑定
     * @param queue 普通队列
     * @param exchange 直连交换机
     * @return Binding 对象,它代表了这个绑定关系。
     *
     * 这个方法的作用是创建一个绑定(Binding),将指定的队列
     * (通过 @Qualifier("orderNormalDelayQueue") 注解注入的 queue 参数)
     * 与指定的交换机(通过 @Qualifier("orderNormalExchange") 注解注入的 exchange 参数)绑定在一起。
     * 参数 queue 是一个普通队列,参数 exchange 是一个直连交换机(Direct Exchange)。
     * 这个方法通过 BindingBuilder.bind(queue).to(exchange).with("normal_order") 创建了一个绑定
     * 将队列 queue 绑定到交换机 exchange,并且指定了一个路由键(Routing Key)为 "normal_order"。
     */
    @Bean
    public Binding orderQueueBindingToOrderExchange(@Qualifier("orderNormalDelayQueue") Queue queue,
                                                    @Qualifier("orderNormalExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("normal_order");
    }

    /**
     * 死信队列与与死信交换机进行绑定
     * @param queue 一个延迟队列
     * @param exchange 直连交换机
     * @return Binding 对象,它代表了这个绑定关系
     *
     * 这个方法的作用是创建一个绑定(Binding),将指定的队列(通过 @Qualifier("delayDelayQueue") 注解注入的 queue 参数)
     * 与指定的死信交换机(通过 @Qualifier("deadDelayExchange") 注解注入的 exchange 参数)绑定在一起。
     * 参数 queue 是一个延迟队列,参数 exchange 是一个直连交换机(Direct Exchange)。
     * 这个方法通过 BindingBuilder.bind(queue).to(exchange).with("expire") 创建了一个绑定
     * 将队列 queue 绑定到交换机 exchange,并且指定了一个路由键(Routing Key)为 "expire"。
     * 当延迟队列中的消息过期后,会被发送到死信交换机中,并且使用路由键 "expire" 进行路由。
     */
    @Bean
    public Binding DelayQueueBingingToDeadExchange(@Qualifier("delayDelayQueue") Queue queue,
                                                   @Qualifier("deadDelayExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("expire");
    }

}

2.4 下单的时候发送消息
 

if (orderMapper.insert(orderInsertEntity)>0) {
   //生产者生产消息
   logger.info("当前时间:{}订单入库成功,订单Id:{},正在发送到RabbitMQ,超时时间:{}s", LocalDateTime.now(), orderInsertEntity.getId(), 30 * 60 * 1000);
   try {
        String orderJson  = objectMapper.writeValueAsString(orderInsertEntity.getId());
        rabbitTemplate.convertAndSend("normal_order_exchange", "normal_order", orderJson,message -> {
            message.getMessageProperties().setExpiration(String.valueOf(30 * 60 * 1000L));
            return message;
        });
       } catch (JsonProcessingException e) {
         logger.error("EQOrderJson序列化失败");
             e.printStackTrace();
        }
}

说明:
message.getMessageProperties().setExpiration(String.valueOf(30 * 60 * 1000L));
 30 * 60 * 1000L这个是设置时间的,我这边设置的是下单超过30分钟如果没付款就会自动取消订单,我这个业务不是卖商品所以不涉及到库存,如果涉及到减库存。如果要是在2.5中收到死信消息后记得加库存。

2.5新建一个监听器。
这一步其实就收下单半个小时后,收到消息了,会先查看一下订单状态,如果是未付款的情况下,就把订单给取消了。
 文章来源地址https://www.toymoban.com/news/detail-852599.html


import com.cx.sasmc.entity.Order;
import com.cx.sasmc.mapper.OrderMapper;
import com.cx.sasmc.orderstatus.OrderStatusConstants;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;

/**
 * <p>
 * 创建监听器(消费者端),用于接收超时未支付的订单,并对该订单进行处理
 * </p>
 *
 * @author Lch
 * @dateTime 2024/4/1 14:29
 */
@Component
public class OrderListener {
    private final Logger logger = LoggerFactory.getLogger(OrderListener.class);
    private final ObjectMapper objectMapper = new ObjectMapper();
    @Resource
    private OrderMapper orderMapper;


    @RabbitListener(queues = {"normal_delay_queue"})
    public void orderExpire(Message message) throws IOException {
        // 使用JackSon反序列化
        String orderNo = objectMapper.readValue(message.getBody(), String.class);
        orderNo = orderNo.replace("\"", "");
        logger.info("----------------------------------------------------");
        logger.info("当前时间:{},订单超时检查订单支付状态,订单信息:{}", LocalDateTime.now(), orderNo);
        // 通过订单Id查询该订单超时后的支付状态
        Order order = orderMapper.selectById(orderNo);
        // 如果订单状态为未支付则将此订单状态关闭
        try {
            if (order.getOrderStatus() == OrderStatusConstants.UNPAID) {
                logger.info("当前时间:{},订单超时关闭订单,订单信息:{}", LocalDateTime.now(), orderNo);
                Order orderUp = new Order();
                orderUp.setId(Long.valueOf(orderNo));
                orderUp.setOrderStatus(OrderStatusConstants.CANCELED);
                orderUp.setFeedback("订单超时未支付!");
                orderMapper.updateById(orderUp);
            }
            logger.info("----------------------------------------------------");
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

到了这里,关于SpringBoot+RabbitMQ实现超时未支付订单自动取消,localhost:15672没有登录页面。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 生成订单30分钟未支付,则自动取消,该怎么实现?

    今天给大家上一盘硬菜,并且是支付中非常重要的一个技术解决方案,有这块业务的同学注意自己试一把了哈! 在开发中,往往会遇到一些关于延时任务的需求。例如 生成订单30分钟未支付,则自动取消 生成订单60秒后,给用户发短信 对上述的任务,我们给一个专业的名字来

    2024年02月09日
    浏览(32)
  • 订单自动取消的11种实现方式(下)

    在Redis中,有个发布订阅的机制 生产者在消息发送时需要到指定发送到哪个channel上,消费者订阅这个channel就能获取到消息。图中channel理解成MQ中的topic。 并且在Redis中,有很多默认的channel,只不过向这些channel发送消息的生产者不是我们写的代码,而是Redis本身。这里面就有

    2024年02月13日
    浏览(25)
  • 商城系统中30分钟未付款自动取消订单怎么实现(简单几种方法)

    实现以上功能 写一个定时任务,每隔 30分钟执行一次,列出所有超出时间范围得订单id的列表 批量执行取消订单操作 实现一个简单的队列,每隔一定时间执行队列。 这里使用队列的优势可以跟前端时间匹配上,前端读秒几秒这里就什么时候取消  使用mq队列,消费消息。如

    2024年01月24日
    浏览(25)
  • 使用RabbitMQ死信队列关闭未支付的订单

    RabbitMQ死信队列(Dead-Letter Exchange,简称DLX)是一种特殊类型的交换机,用于处理在队列中无法被消费的消息。当消息无法被消费时,它会被转发到死信队列中,以便进一步处理。 在RabbitMQ中,死信队列通常用于处理以下情况: 消息无法被消费者处理:例如,如果消费者崩溃

    2024年02月11日
    浏览(29)
  • 简单的RabbitMQ集成Springboot实现订单异步发送功能示例以及RabbitMQ的相关问题

    引入RabbitMQ的依赖,在pom.xml文件中添加以下代码: 在application.properties文件中配置RabbitMQ的相关信息: 创建消息队列,并定义消息接收者: 定义消息发送者: 在需要发送订单信息的地方调用OrderSender的send方法即可: RabbitMQ是一个开源的消息中间件,主要用于实现应用之间的异

    2024年02月09日
    浏览(25)
  • Spring Boot中实现订单30分钟自动取消的策略

    🎉欢迎来到架构设计专栏~Spring Boot中实现订单30分钟自动取消的策略 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:架构设计 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水平有限,

    2024年02月08日
    浏览(43)
  • 03、SpringBoot + 微信支付 ---- 创建订单、保存二维码url、显示订单列表

    1-1:需求: 之前的下单,只是获取支付二维码,但是并没有将订单存到数据库 需求1:点击确认支付后,创建商品的订单存到数据库 需求2:每次确认支付之前,要判断这个人是否存在已下单未支付的订单,有的话就不用再创建订单了,把他的订单查询出来给他就行。 1-2:代

    2024年02月05日
    浏览(38)
  • Spring Boot整合Redis实现订单超时处理

    🎉欢迎来到架构设计专栏~Spring Boot整合Redis实现订单超时处理 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:架构设计 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水平有限,如果文

    2024年02月03日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包