rabbitMq延迟队列实现订单失败(订单过期)

1.订单失效原理

订单失效的实现方式
1:redis的过期特性,redis提供了key过期的监听事件接口,通过监听key过期来实现订单失效,不支持集群环境(主从结构存在数据副本)
2:使用rabbitMq实现延迟队列的功能。

image-20211103143950416

  1. 当生成订单时,将订单号放入死信队列(因为没有消息处理者,所以称为死信队列)设置消息的存活时间为30分钟,
  2. 当30分钟过后,死信队列的消息会通过,路由转发交换机,路由转发交换机将消息发给工作队列
  3. 消息处理者处理消息

2.具体实现

  • 导入相应的jar包
<!--spring整合rabbitMq -->
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.1.2</version>
</dependency>
<!-- spring整合rabbitMq-->
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>
  • 配置rabbit配置文件spring-rabbit.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/rabbit
        http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <!-- 连接工厂-->
    <!-- 创建连接工厂将来生产连接,工厂名为rabbitConnectionFactory,登陆名为admin,密码为admin,连接地址为192.168.192.3 ,端口号为5672-->
    <rabbit:connection-factory id="rabbitConnectionFactory" username="admin" password="admin" host="192.168.192.3" port="5672"/>

    <!--以管理员身份使用上面这个连接工厂 -->
    <rabbit:admin connection-factory="rabbitConnectionFactory"/>
    <!-- 死信队列,队列名为dead_queue。自动声明-->
    <rabbit:queue name="dead_queue" auto-declare="true">
        <!-- 定义队列参数: -->
        <rabbit:queue-arguments>
            <!-- 设置消息的存活时间  毫秒数-->
            <entry key="x-message-ttl" value="30000" value-type="java.lang.Long"/>
            <!-- 引用死信路由器 -->
            <entry key="x-dead-letter-exchange" value="dead_exchange"/>
            <!-- 设置死信路由键 -->
            <entry key="x-dead-letter-routing-key" value="task_queue"/>
        </rabbit:queue-arguments>
    </rabbit:queue>

    <!-- dead_exchange死信交换机-->
    <rabbit:direct-exchange name="dead_exchange" durable="false" auto-delete="false" id="dead_exchange">
        <!-- 死信理由绑定转发的队列-->
        <rabbit:bindings>
            <rabbit:binding queue="task_queue"/>
        </rabbit:bindings>
    </rabbit:direct-exchange>

    <!-- 任务队列-->
    <!-- 消费者所获取的消息队列-->
    <rabbit:queue name="task_queue" auto-declare="true" />
    <!-- 线程池-->
    <!-- 消费者消费消息的任务类
     线程池去调度线程去执行任务类的方法
     -->
    <!-- 配置线程池 -->
    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <!-- 线程池维护线程的最少数量 -->
        <property name="corePoolSize" value="5"/>
        <!-- 线程池维护线程所允许的空闲时间 -->
        <property name="keepAliveSeconds" value="30000"/>
        <!-- 线程池维护线程的最大数量 -->
        <property name="maxPoolSize" value="2000"/>
        <!-- 线程池所使用的缓冲队列 -->
        <property name="queueCapacity" value="20"/>
    </bean>

    <!-- 监听程序监听任务队列消费-->
    <!-- 配置监听容器-->
    <rabbit:listener-container connection-factory="rabbitConnectionFactory" acknowledge="auto" task-executor="taskExecutor">
        <!-- 指定监听队列 使用哪个监听类, 定义了 收到消息之后的逻辑 ,来监听-->
        <rabbit:listener queues="task_queue" ref="delayTask"/>
    </rabbit:listener-container>

    <!-- 消息消费的任务类-->
    <bean id="delayTask" class="com.oracle.shop.task.OrdersExpireMessageTask"/>

    <!-- 配置生产消息的客户端对象,将来发送消息到dead_queue -->
    <!-- 实例化一个生产者客户端对象,将来向dead_queue写消息
   spring封装了amqpTempalte
   -->
    <rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory" queue="dead_queue" routing-key="dead_queue"/>
</beans>
  • 编写处理类
//订单过期处理
public class OrdersExpireMessageTask implements MessageListener {

    @Autowired
    private OrdersService ordersService;

    //消费者监听队列进行处理
    @Override
    public void onMessage(Message message) {
        //消息过期后,接收并进行处理
        String orderNumber = new String(message.getBody());
        //查询订单状态,如果未支付,则查询支付宝接口,确认订单状态,然后进行操作
        Orders orders = ordersService.selectOrdersByOrdersNum(orderNumber);
        if (orders.getOrdersStatus() == 0) {//未支付
            //通过支付包验证订单是否支付
            try {
                AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                        AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                        AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
                //创建查询请求
                AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
                //设置请求参数
                alipayTradeQueryRequest.setBizContent("{" + "\"out_trade_no\":\"" + orderNumber + "\"" + "}");
                //执行查询,返回查询结果
                AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(alipayTradeQueryRequest);
                //对查询结果进行处理
                if (alipayTradeQueryResponse.isSuccess()) {
                    switch (alipayTradeQueryResponse.getTradeStatus()) // 判断交易结果
                    {
                        case "TRADE_FINISHED": // 交易结束并不可退款,修改订单状态为已支付
                            ordersService.updateOrdersStatusPaied(orderNumber);
                            break;
                        case "TRADE_SUCCESS": // 交易支付成功,修改订单状态为,已支付
                            ordersService.updateOrdersStatusPaied(orderNumber);
                            break;
                        case "TRADE_CLOSED": // 未付款交易超时关闭或支付完成后全额退款,修改订单状态为,未支付
                            ordersService.updateOrdersStatusOverdue(orderNumber);
                            break;
                        case "WAIT_BUYER_PAY": // 交易创建并等待买家付款,修改订单状态为,未支付
                            ordersService.updateOrdersStatusOverdue(orderNumber);
                            break;
                        default:
                            break;
                    }
                } else {//支付宝方面没有该订单,直接修改订单信息为过期
                    ordersService.updateOrdersStatusOverdue(orderNumber);
                }
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
        }
    }
}
posted @ 2021-11-06 13:10  2333gyh  阅读(699)  评论(0编辑  收藏  举报