15年软件开发经验 只做源码定制 互联网+定制化解决方案

15年软件开发经验,只做源码定制!

原创设计 定制开发

满足您的个性化需求

当前位置:首页 后端开发 java

Spring Boot + RabbitMQ(消息中间件)实现订单超时自动取消功能

庞凯博| 发布于 2021-12-17 23:54:34| 268阅读| 0点赞| 0评论
举报

场景:在商城中下单,订单创建成功,等待支付,一般会给30分钟的时间,开始倒计时。如果在这段时间内 用户没有支付,则默认订单取消。

如何订单超时实现?
  • 定时任务
  • redission延时任务
  • rabbitmq死信队列
本文将以rabbitmq死信队列展开做讲解。
软件准备

安装环境 erlang

队列 RabbitMQ

启动RabbitMQ,然后添加一个用户, 并给用户设置权限

# 后台启动
rabbitmq-server -detached
# 添加用户
rabbitmqctl add_user root 123456
# 设置用户权限:
rabbitmqctl set_permissions -p "/" root ".*" ".*" ".*"

接下来创建一个springboot工程,并集成RabbitMQ。


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.8.RELEASEversion>
        <relativePath/> 
    parent>
    <groupId>com.lagougroupId>
    <artifactId>rabbitmq-workartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>rabbitmq-workname>
    <description>Demo project for Spring Bootdescription>
    <properties>
        <java.version>1.8java.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-amqpartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
            <scope>runtimescope>
        dependency>
        
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.3.2version>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>

    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

接下来在application.yml配置文件中假如rabbitmq配置

spring:
  application:
    name: rabbit-work
  # rabbitmq配置
  rabbitmq:
    host: localhost
    virtual-host: /
    username: root
    password: 123456
  # redis配置
  redis:
    timeout: 6000
    host: localhost
    port: 6379
    database: 0
  # 数据源配置
  datasource:
    url: jdbc:mysql://localhost:3306/order?useunicode=true&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    hikari:
      minimum-idle: 3
      maximum-pool-size: 5
      max-lifetime: 30000
      connection-init-sql: SELECT 1
# mybatis-plus配置
mybatis-plus:
  mapper-locations: classpath:com.lagou.*.mapper/*.xml
  type-aliases-package: com.lagou.*.domain

定义RabbitConfig

@Configuration
public class RabbitConfig {

    /**
     * 订单队列
     *
     * @return {@link Queue}
     */
    @Bean
    public Queue orderQueue() {
        Map argments = new HashMap<>();
        argments.put("x-message-ttl", 60000);
        argments.put("x-dead-letter-exchange", RabbitConstants.ORDER_DLX_EXCHANGE);
        argments.put("x-dead-letter-routing-key", RabbitConstants.ORDER_DLX_ROUTING_KEY);
        Queue queue = new Queue(RabbitConstants.ORDER_QUEUE, true, false, false, argments);
        return queue;
    }

    /**
     * 订单交换机
     *
     * @return {@link Exchange}
     */
    @Bean
    public Exchange orderExchange() {
        return new DirectExchange(RabbitConstants.ORDER_EXCHANGE, true, false, null);
    }

    /**
     * 订单路由键
     *
     * @return {@link Binding}
     */
    @Bean
    public Binding orderRouting() {
        return BindingBuilder.bind(orderQueue()).to(orderExchange()).with(RabbitConstants.ORDER_ROUTING_KEY).noargs();
    }

    /**
     * 订单死信队列
     *
     * @return {@link Queue}
     */
    @Bean
    public Queue orderDlxQueue() {
        Queue queue = new Queue(RabbitConstants.ORDER_DLX_QUEUE, true, false, false);
        return queue;
    }

    /**
     * 订单死信交换机
     *
     * @return {@link Exchange}
     */
    @Bean
    public Exchange orderDlxExchange() {
        return new DirectExchange(RabbitConstants.ORDER_DLX_EXCHANGE, true, false, null);
    }

    /**
     * 订单死信路由键
     *
     * @return {@link Binding}
     */
    @Bean
    public Binding orderDlxRouting() {
        return BindingBuilder.bind(orderDlxQueue()).to(orderDlxExchange()).with(RabbitConstants.ORDER_DLX_ROUTING_KEY).noargs();
    }

    /**
     * 库存队列
     *
     * @return {@link Queue}
     */
    @Bean
    public Queue stockQueue() {
        return new Queue(RabbitConstants.STOCK_QUEUE, true, false, false, null);
    }

    /**
     * 库存交换机
     *
     * @return {@link Exchange}
     */
    @Bean
    public Exchange stockExchange() {
        return new DirectExchange(RabbitConstants.STOCK_EXCHANGE, true, false, null);
    }

    /**
     * 库存路由键
     *
     * @return {@link Binding}
     */
    @Bean
    public Binding stockRouting() {
        return BindingBuilder.bind(stockQueue()).to(stockExchange()).with(RabbitConstants.STOCK_ROUTING_KEY).noargs();
    }

}

实现消息发送

@RequestMapping(value = "/submit", produces = "application/json;charset=UTF-8")
public R submit(@RequestBody OrderVo orderVo) throws UnsupportedEncodingException {
	Order order = orderService.createOrder(orderVo);
	System.out.println("OrderController.submit... createOrder");

	// 放入死信队列
	amqpTemplate.convertAndSend(RabbitConstants.ORDER_EXCHANGE,
			RabbitConstants.ORDER_ROUTING_KEY,
			(order.getId() + ""));
	System.out.println("OrderController.submit... sendMessage to orderExchange");
	return R.ok(order);
}

消息消费者监听

@Component
public class OrderHandler {

    @Autowired
    private OrderService orderService;

    @RabbitListener(queues = RabbitConstants.ORDER_DLX_QUEUE, ackMode = "MANUAL")
    public void onMessage(Message message, Channel channel) throws IOException {
        System.out.println("消息进入死信队列...");
        String s = new String(message.getBody());
        Order o = orderService.getById(Long.parseLong(s));
        if (o != null && OrderConstants.TOPAID.getCode().equals(o.getOrderState())) {
            Order order = new Order();
            order.setId(o.getId());
            order.setOrderState(OrderConstants.CANCEL.getCode());
            order.setGmtModified(new Date());
            orderService.updateById(order);
        }
        // 手动ack
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
0

0条评论

别默默看啦~登录/注册一起参与讨论吧~

热门标签

庞凯博
微信扫一扫立即咨询
账号登录|扫码登录

立即注册 |忘记密码?

欢迎注册

已有账号马上登录

重置密码

扫码绑定微信
微信扫一扫

绑定手机号

分享到-微信

举报

  • 举报类型:

  • 举报描述:

您好,当前积分不足。

在线客服
拨打电话
17330196230 13230981129
顶部