SpringBoot整合RabbitMQ

SpringBoot整合RabbitMQ

建议把配置放到消费者:因为消费者是最先起来的服务。比如你想下订单,最好就是你下订单,马上就能给出正确反馈,这样消费者必须得时刻备着来处理订单。

fanout模式(订单案例)

image-20220901222720696

  1. 依赖
<!--rabbitMQ依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  1. 配置文件
# 配置rabbitmq服务
spring:
  rabbitmq:
    username: guest
    password: guest
    virtual-host: /
    host: 192.168.181.200
    port: 5672
  1. 配置类,写好交换机和队列的绑定关系
package com.xuexiangban.rabbitmq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 17:34
 */
@Configuration
public class RabbitMqConfiguration {
    //1. 声明注册fanout模式的交换机
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("fanout_order_exchange", true, false);
    }

    //2. 声明队列sms.fanout.queue; email.fanout.queue; duanxin.fanout.queue
    @Bean
    public Queue smsQueue(){
        return new Queue("sms.fanout.queue", true);
    }
    @Bean
    public Queue emailQueue(){
        return new Queue("email.fanout.queue", true);
    }
    @Bean
    public Queue duanxinQueue(){
        return new Queue("duanxin.fanout.queue", true);
    }

    //3. 完成绑定关系(队列和交换机)
    @Bean
    public Binding smsBinding() {
        return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
    }
    @Bean
    public Binding emailBinding() {
        return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
    }
    @Bean
    public Binding duanxinBinding() {
        return BindingBuilder.bind(duanxinQueue()).to(fanoutExchange());
    }
}
  1. 生产者
package com.xuexiangban.rabbitmq.service;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 17:22
 */
@Service
public class OrderService {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    /** 
    * @Description: 模拟用户下单
    * @return: void
    */
    public void makeOrder(String userId,String productId,int num){
        //1. 根据id查询库存是否充足
        //2. 保存订单
        String orderId = UUID.randomUUID().toString();
        System.out.println("订单生成成功:" + orderId);
        //3. 通过MQ完成消息的分发
        //(1)交换机 (2)路由key/queue队列名称 (3)消息内容
        String exchangeName = "fanout_order_exchange";
        String routingKey = "";
        rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
    }
}
  1. 消费者

消费者为另外的一个springboot模块

(1)先依赖后配置文件,记得端口要和上面的端口不一样

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
# 服务端口
server:
  port: 8081
# 配置rabbitmq服务
spring:
  rabbitmq:
    username: guest
    password: guest
    virtual-host: /
    host: 192.168.181.200
    port: 5672

(2)消费者类

记得加@Component注解,交给SpringBoot管理

@RabbitListener(queues = {"duanxin.fanout.queue"}) :绑定队列,加在类上

@RabbitHandler :队列中接受到的消息传到下面的参数中,加在方法上

package com.xuexiangban.rabbitmq.service.fanout;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 22:32
 */
@RabbitListener(queues = {"duanxin.fanout.queue"})
@Component
public class FanoutDuanxinConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("duanxin fanout---接受到的消息是:" + message);
    }
}
package com.xuexiangban.rabbitmq.service.fanout;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 22:32
 */
@RabbitListener(queues = {"email.fanout.queue"})
@Component
public class FanoutEmailConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("email fanout---接受到的消息是:" + message);
    }
}
package com.xuexiangban.rabbitmq.service.fanout;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 22:32
 */
@RabbitListener(queues = {"sms.fanout.queue"})
@Component
public class FanoutSMSConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("sms fanout---接受到的消息是:" + message);
    }
}
  1. 然后启动消费者启动类,就可以监听队列,然后消费了
package com.xuexiangban.rabbitmq;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootOrderRabbitmqConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootOrderRabbitmqConsumerApplication.class, args);
    }

}

第二次提交了Direct模式(订单案例)

  1. 生产者

照比fanout模式,Direct多了个RoutingKey

​ 配置类:交换机和队列的绑定关系(将FanoutExchange改为DirectExchange,并且绑定的时候BindingBuilder.bind(“队列”).to(“交换机”).with("RoutingKey"); 多了一个with方法用于绑定RoutingKey)

package com.rabbitmq.springbootorderrabbitmqproducer.config;

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

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 17:34
 */
@Configuration
public class DirectRabbitMqConfiguration {
    //1. 声明注册direct模式的交换机
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("direct_order_exchange", true, false);
    }

    //2. 声明队列sms.direct.queue; email.direct.queue; duanxin.direct.queue
    @Bean
    public Queue directsmsQueue(){
        return new Queue("sms.direct.queue", true);
    }
    @Bean
    public Queue directemailQueue(){
        return new Queue("email.direct.queue", true);
    }
    @Bean
    public Queue directduanxinQueue(){
        return new Queue("duanxin.direct.queue", true);
    }

    //3. 完成绑定关系(队列和交换机)
    @Bean
    public Binding directsmsBinding() {
        return BindingBuilder.bind(directsmsQueue()).to(directExchange()).with("sms");
    }
    @Bean
    public Binding directemailBinding() {
        return BindingBuilder.bind(directemailQueue()).to(directExchange()).with("email");
    }
    @Bean
    public Binding directduanxinBinding() {
        return BindingBuilder.bind(directduanxinQueue()).to(directExchange()).with("duanxin");
    }
}

​ Service方法:记得交换机的名字已经改变

/**
    * @Description: 模拟用户下单
    * @return: void
    */
public void makeOrderDirect(String userId,String productId,int num){
    //1. 根据id查询库存是否充足
    //2. 保存订单
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功:" + orderId);
    //3. 通过MQ完成消息的分发
    //(1)交换机 (2)路由key/queue队列名称 (3)消息内容
    String exchangeName = "direct_order_exchange";
    rabbitTemplate.convertAndSend(exchangeName, "sms", orderId);
    rabbitTemplate.convertAndSend(exchangeName, "duanxin", orderId);
}
  1. 消费者:把队列名称改一下
@RabbitListener(queues = {"duanxin.direct.queue"})
@Component
public class DirectDuanxinConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("duanxin fanout---接受到的消息是:" + message);
    }
}
  1. 如果先启动消费者,把第一步的绑定关系,也可以同时配置到生产者
package com.rabbitmq.springbootorderrabbitmqconsumer.config;

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

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 17:34
 */
@Configuration
public class DirectRabbitMqConfiguration {
    //1. 声明注册direct模式的交换机
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("direct_order_exchange", true, false);
    }

    //2. 声明队列sms.direct.queue; email.direct.queue; duanxin.direct.queue
    @Bean
    public Queue smsQueue(){
        return new Queue("sms.direct.queue", true);
    }
    @Bean
    public Queue emailQueue(){
        return new Queue("email.direct.queue", true);
    }
    @Bean
    public Queue duanxinQueue(){
        return new Queue("duanxin.direct.queue", true);
    }

    //3. 完成绑定关系(队列和交换机)
    @Bean
    public Binding smsBinding() {
        return BindingBuilder.bind(smsQueue()).to(directExchange()).with("sms");
    }
    @Bean
    public Binding emailBinding() {
        return BindingBuilder.bind(emailQueue()).to(directExchange()).with("email");
    }
    @Bean
    public Binding duanxinBinding() {
        return BindingBuilder.bind(duanxinQueue()).to(directExchange()).with("duanxin");
    }
}

第三次提交了Topic模式(订单案例)

在消费者那里,利用注解的方式将交换机与队列进行绑定(推荐用配制文件方式)

  1. 生产者
public void makeOrderTopic(String s, String s1, int i) {
    //1. 根据id查询库存是否充足
    //2. 保存订单
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功:" + orderId);
    //3. 通过MQ完成消息的分发
    //(1)交换机 (2)路由key/queue队列名称 (3)消息内容
    String exchangeName = "topic_order_exchange";
    //sms:com.#
    //email:*.email.#
    //duanxin:#.duanxin.#
    String routingKey = "com.email.duanxin";
    rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
@Test
void testOrderTopic() {
    orderService.makeOrderTopic("1","1",12);
}
  1. 消费者(注解配置队列交换机)
package com.rabbitmq.springbootorderrabbitmqconsumer.service.topic;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 22:32
 */
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "duanxin.topic.queue", durable = "true", autoDelete = "false"),
        exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
        key = "#.sms.#"
))
@Component
public class TopicDuanxinConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("duanxin topic---接受到的消息是:" + message);
    }
}
package com.rabbitmq.springbootorderrabbitmqconsumer.service.topic;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 22:32
 */
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "email.topic.queue", durable = "true", autoDelete = "false"),
        exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
        key = "*.email.#"
))
@Component
public class TopicEmailConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("email topic---接受到的消息是:" + message);
    }
}
package com.rabbitmq.springbootorderrabbitmqconsumer.service.topic;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 22:32
 */
@Component
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "sms.topic.queue", durable = "true", autoDelete = "false"),
        exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
        key = "com.#"
))
public class TopicSMSConsumer {
    @RabbitHandler
    public void reviceMessage(String message) {
        System.out.println("sms topic---接受到的消息是:" + message);
    }
}

第四次提交了TTL队列以及消息过期时间

当两者都设置了过期时间,已过期时间短者为标准。

  1. 生产者(队列)
package com.rabbitmq.springbootorderrabbitmqproducer.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Pillar
 * @version 1.0
 * @date 2022/9/1 17:34
 */
@Configuration
public class TTLRabbitMqConfiguration {
    @Bean
    public DirectExchange TTLdirectExchange(){
        return new DirectExchange("ttl_direct_exchange", true, false);
    }

    @Bean
    public Queue ttlQueue(){
        //设置过期时间
        Map<String, Object> args = new HashMap<>();
        args.put("x-message-ttl", 5000);
        return new Queue("ttl.direct.queue", true,false,false,args);
    }

    @Bean
    public Binding ttlBinding() {
        return BindingBuilder.bind(ttlQueue()).to(TTLdirectExchange()).with("ttl");
    }
}
public void makeOrderTtl(String s, String s1, int i) {
    //1. 根据id查询库存是否充足
    //2. 保存订单
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功:" + orderId);
    //3. 通过MQ完成消息的分发
    //(1)交换机 (2)路由key/queue队列名称 (3)消息内容
    String exchangeName = "ttl_direct_exchange";

    String routingKey = "ttl";
    rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
@Test
void testOrderTtl() {
    orderService.makeOrderTtl("1","1",12);
}
  1. 生产者(消息)

在生产者指定交换机和路由id,在配置个延时消息

public void makeOrderTtlMsg(String s, String s1, int i) {
    //1. 根据id查询库存是否充足
    //2. 保存订单
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功:" + orderId);
    //3. 通过MQ完成消息的分发
    //(1)交换机 (2)路由key/queue队列名称 (3)消息内容
    String exchangeName = "ttl_direct_exchange";
    String routingKey = "ttlmessage";
    //给消息设置过期时间
    MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){
        @Override
        public Message postProcessMessage(Message message) throws AmqpException {
            message.getMessageProperties().setExpiration("5000");
            message.getMessageProperties().setContentEncoding("UTF-8");
            return message;
        }
    };
    rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId,messagePostProcessor);
}

绑定交换机和普通队列

@Bean
public Binding ttlMsgBinding() {
    return BindingBuilder.bind(ttlMessageQueue()).to(TTLdirectExchange()).with("ttlmessage");
}

测试

@Test
void testOrderTtlMsg() {
    orderService.makeOrderTtlMsg("1","1",12);
}

总结

生产者,

先写配置类,写好交换机和队列的绑定关系

再写Service方法,指定好交换机的名称以及队列名,用到

rabbitTemplate.convertAndSend(交换机, 队列名, 消息);

消费者,

写好消费者类,@RabbitListener(queues = {"**.queue"}) 指定消费的队列名,用@RabbitHandler 放在方法上,消息会传递给给方法的参数上

posted @   NeverLateThanBetter  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
点击右上角即可分享
微信分享提示