Spring Boot 2.1.9 整合 RabbitMQ 实现延时队列处理超时未支付订单

前置条件

RabbitMQ服务端需要安装rabbitmq_delayed_message_exchange插件

CentOS7 为RabbitMQ安装延时队列插件

一)、引入依赖


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-amqpartifactId>
dependency>

二)、在需要使用RabbitMQ的服务模块编写配置文件

spring:
  rabbitmq:
    host: 127.0.0.1
    username: 123456
    password: 123456
    port: 5672
    # 开启消息手动应答
    listener:
      direct:
        acknowledge-mode: MANUAL
      simple:
        acknowledge-mode: MANUAL

三)、编写RabbitMQ配置类

/**
 * RabbitMQ 配置类
 * 

* 说明: * 1. 定义超时支付订单队列 * 2. 定义广播模式的延时交换机 * 3. 绑定超时支付订单队列与延时交换机 * 4. 定义消息模板用于发布消息,并且设置其消息转换器 * * @author MoCha * @date 2020/4/14 */ public class RabbitMqConfig { /** * 定义超时支付订单队列 * * @return 超时支付订单队列 */ @Bean public Queue timeOutOrderQueue() { // 表示持久化该队列,RabbitMQ服务重启后该队列仍旧保留 return QueueBuilder.durable(RabbitMqConstants.TIMEOUT_ORDER_QUEUE).build(); } /** * 定义广播模式的延时交换机 无需绑定路由 */ @Bean public Exchange delayExchange() { Map<String, Object> arguments = new HashMap<>(4); arguments.put("x-delayed-type", "direct"); // 如果不调用autoDelete()方法,那么autoDelete就是false // 可以不调用durable(boolean isDurable),默认为true // 调用delayed()后,delayed变量设置为true return ExchangeBuilder.fanoutExchange(RabbitMqConstants.DELAY_EXCHANGE) .withArguments(arguments).delayed().build(); } /** * 绑定超时支付订单队列与延时交换机 */ @Bean public Binding delayExchangeAndTimeOutOrderQueueBinding() { return BindingBuilder.bind(timeOutOrderQueue()).to(delayExchange()).with(StringPool.EMPTY).noargs(); } /** * 定义消息转换器 */ @Bean Jackson2JsonMessageConverter jsonMessageConverter() { return new Jackson2JsonMessageConverter(); } /** * 定义消息模板用于发布消息,并且设置其消息转换器 */ @Bean RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); // 定义消息转换器并设置 rabbitTemplate.setMessageConverter(jsonMessageConverter()); return rabbitTemplate; } @Bean RabbitAdmin rabbitAdmin(final ConnectionFactory connectionFactory) { return new RabbitAdmin(connectionFactory); } }

RabbitMQ常量类

/**
 * RabbitMQ 常量类
 *
 * @author MoCha
 * @date 2020/4/14
 */
public final class RabbitMqConstants {
     
    /**
     * 超时支付订单 延时交换机
     */
    public static final String DELAY_EXCHANGE = "delay.exchange";

    /**
     * 超时支付订单 延时队列
     */
    public static final String TIMEOUT_ORDER_QUEUE = "timeout_order_queue";

    /**
     * 阻止实例化
     * 

* Prevents instantiation */ private RabbitMqConstants() { } }

四)、编写开启RabbitMQ注解

在需要使用RabbitMQ的主启动类上添加该注解

/**
 * 开启 RabbitMQ
 *
 * @author MoCha
 * @date 2020/4/15
 */
@Documented
@Target({
     ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(RabbitMqConfig.class)
public @interface EnableRabbitMq {
     
}
/**
 * 在主启动类上添加@EnableRabbitMq,引入我们编写的RabbitMQ配置类
 *
 * @author MoCha
 * @date 2020/4/15
 */
@EnableRabbitMq
@SpringBootApplication(scanBasePackages = {
     "top.yangzefeng.server.marketing", "top.yangzefeng.common"})
public class IceStreamServerMarketingApplication {
     
    public static void main(String[] args) {
     
        SpringApplication springApplication = new SpringApplication(IceStreamServerMarketingApplication.class);
        springApplication.setBanner(new IceStreamBanner());
        springApplication.run(args);
    }
}

五)、编写Controller

/**
 * @author MoCha
 * @date 2020/4/15
 */
@Slf4j
@RestController
@RequestMapping("/rabbitmq")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
     
    /**
     * 超时支付延时时间
     * 

* 说明: * 1. 根据message.getMessageProperties().setDelay(timeoutDelayTime);可知setDelay的参数类型为Integer */ @Value("${rabbitmq.timeOutDelayTime}") private Integer timeoutDelayTime; private final RabbitTemplate rabbitTemplate; private final OrderService orderService; @GetMapping("/test") public String createOrderTest() { // 创建订单 Order order = new Order(); order.setOrderId(IdWorker.getId()); order.setOrderTradeNumber(IdWorker.getTimeId()); order.setUserId(0); order.setOrderAmount(BigDecimal.TEN); order.setOrderStatus(OrderStatusEnum.NOT_PAID.getStatus()); order.setPaymentType(0); order.setOrderType(0); // 发送订单到消息队列 rabbitTemplate.convertAndSend(RabbitMqConstants.DELAY_EXCHANGE, StringPool.EMPTY, order, message -> { message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT); // 毫秒为单位,指定此消息的延时时长,设置10秒延时 message.getMessageProperties().setDelay(timeoutDelayTime); return message; }); orderService.save(order); log.info("创建订单成功"); return "创建订单成功"; } }

六)、编写Listener,监听消息

/**
 * 订单消息监听器
 * 

* 说明: * 1. @RabbitListener指定目标方法来作为消费消息的方法,通过注解参数指定所监听的队列或者Binding * * @author MoCha * @date 2020/4/14 */ @Slf4j @Component @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class OrderListener { /** * 超时支付延时时间 */ @Value("${rabbitmq.timeOutDelayTime}") private Integer timeoutDelayTime; private final OrderService orderService; @RabbitListener(queues = RabbitMqConstants.TIMEOUT_ORDER_QUEUE) public void process(Order order, Message message, Channel channel) throws IOException { log.info("超时时间为 [{}] ms,超时订单信息,order = [{}]", timeoutDelayTime, JsonUtils.prettyPrint(order)); try { orderService.timeOutCloseOrder(order.getOrderId()); channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); log.info("超时订单处理完毕"); } catch (Exception e) { channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); } } }

说明

  • 由于Order实体类使用了LocalDateTime,并且服务自身内部对LocalDateTime序列化和反序列化作了处理,参考Spring Boot Java8 LocalDateTime日期序列化与反序列化 解决方案,所以在RabbitMQ配置类中,不需要再另外设置jsonMessageConverter,以及将jsonMessageConverter填充到RabbitTemplate

  • 说明:不同版本的spring boot,对于使用BindingBuilder来创建Binding使用方式有点差异

  • /**
     * 绑定超时支付订单队列与延时交换机
     * 
     */
    @Bean
    public Binding delayExchangeAndTimeOutOrderQueueBinding() {
           
    	// 2.1.9.RELEASE
    	// 通过分析2.2.6.RELEASE版本下,BindingBuilder源码的处理,可以改造成这样
    	return BindingBuilder.bind(timeOutOrderQueue()).to(delayExchange()).with(StringPool.EMPTY).noargs();
    }
    @Bean
    public Binding delayExchangeAndTimeOutOrderQueueBinding() {
           
    	// 2.2.6.RELEASE
    	return BindingBuilder.bind(timeOutOrderQueue()).to(delayExchange());
    }
    
  • <parent>
    	<groupId>org.springframework.bootgroupId>
    	<artifactId>spring-boot-starter-parentartifactId>
    	<version>2.1.9.RELEASEversion>
    	<relativePath/>
    parent>
    <dependency>
    	<groupId>org.springframework.bootgroupId>
    	<artifactId>spring-boot-starter-amqpartifactId>
    	 <version>2.1.9.RELEASEversion>
    dependency>
    
    <parent>
    	<groupId>org.springframework.bootgroupId>
    	<artifactId>spring-boot-starter-parentartifactId>
    	<version>2.2.6.RELEASEversion>
    	<relativePath/>
    parent>
    <dependency>
    	<groupId>org.springframework.bootgroupId>
    	<artifactId>spring-boot-starter-amqpartifactId>
    	 <version>2.2.6.RELEASEversion>
    dependency>
    

你可能感兴趣的:(Java进化之旅,Spring,Boot,RabbitMQ,Spring,Boot,RabbitMQ,延时队列,超时未支付,订单管理)