SpringBoot 集成 RabbitMQ(下)

这篇文章内容:SpringBoot 集成 RabbitMQ 的其它模式:工作队列模式、 发布/订阅模式、路由模式、主题模式

1. 工作队列模式 WorkQueue

工作队列模式:一个生产者对应多个消费者

1.1 生产者

生产者工程结构图:
在这里插入图片描述
application.yml

server:
  port: 8081
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /

1》、新配置一个工作队列

@Configuration
public class WorkQueueConfig {

    // 创建队列
    @Bean
    public Queue workQueue() {
        return new Queue(RabbitMqConstant.WORK_QUEUE_NAME);
    }
}

2》、编写发送消息逻辑

@Component
public class WorkProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMsg() {
        for (int i = 0; i < 10; i++) {
            String msg = "工作队列模式下的消息 " + i;
            rabbitTemplate.convertAndSend(RabbitMqConstant.WORK_QUEUE_NAME, msg);
        }
    }
}

常量类

public interface RabbitMqConstant {
    String SIMPLE_QUEUE_NAME = "simple_queue";
    String WORK_QUEUE_NAME = "work_queue";
}

4》、添加一个发送消息的接口

@RestController
@RequestMapping("/work")
public class WorkController {

    @Autowired
    private WorkProducer workProducer;

    @RequestMapping("/sendMsg")
    public String sendMsg() {
        workProducer.sendMsg();
        return "WORK-QUEUE";
    }
}

使用 PostMan 调用此接口:http://localhost:8081/work/sendMsg

1.2 消费者

消费者工程结构图
在这里插入图片描述
application.yml

server:
  port: 8080
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    listener:
      simple:
        acknowledge-mode: manual
        concurrency: 1
        max-concurrency: 2
        retry:
          enabled: true

编写两个消费者:

Component
public class WorkConsumer {

    @RabbitListener(queues = {"work_queue"})
    public void receive(Message message, Channel channel) throws Exception{
        Thread.sleep(1000);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息1:" + new String(message.getBody()));
    }

    @RabbitListener(queues = {"work_queue"})
    public void receive2(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息2:" + new String(message.getBody()));
    }
}

控制台打印,发现10条消息由两个消费者消费,并且平均分配。

通过配置可控分配数实现按需分配,即谁的性能强,谁优先原则,实现负载均衡。

server:
  port: 8080
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    listener:
      simple:
        acknowledge-mode: manual
        concurrency: 1
        max-concurrency: 2
        retry:
          enabled: true
        prefetch: 1 # 每次只处理一个消息

2. 发布/订阅模式(广播模式) Fanout Queue

需要新建一个 Exchange,它的类型为 fanout,不需要路由键。

application.yml 配置文件不变

2.1 生产者

1》、配置队列、交换机、队列与交换机之间的关系

@Configuration
public class FanoutQueueConfig {

    // 声明队列
    @Bean
    public Queue fanoutQueue1() {
        return new Queue(RabbitMqConstant.FAN_OUT_QUEUE_NAME_1);
    }

    @Bean
    public Queue fanoutQueue2() {
        return new Queue(RabbitMqConstant.FAN_OUT_QUEUE_NAME_2);
    }

    // 声明交换机
    @Bean
    public FanoutExchange exchange() {
        return new FanoutExchange(RabbitMqConstant.FAN_OUT_EXCHANGE);
    }

    // 声明交换机与队列之间的关系
    @Bean
    public Binding bindingFanoutQueue1(Queue fanoutQueue1, FanoutExchange exchange) {
        return BindingBuilder.bind(fanoutQueue1).to(exchange);
    }

    @Bean
    public Binding bindingFanoutQueue2(Queue fanoutQueue2, FanoutExchange exchange) {
        return BindingBuilder.bind(fanoutQueue2).to(exchange);
    }
}

2》、发送消息

注意:这里是往交换机中发送消息

@Component
public class FanoutProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMsg() {
        for (int i = 0; i < 10; i++) {
            String msg = "发布/订阅模式下的消息 " + i;
            rabbitTemplate.convertAndSend(RabbitMqConstant.FAN_OUT_EXCHANGE, "", msg);
        }
    }
}

3》、常量类

public interface RabbitMqConstant {
    String SIMPLE_QUEUE_NAME = "simple_queue";
    String WORK_QUEUE_NAME = "work_queue";
    /**
     * fanout
     */
    String FAN_OUT_QUEUE_NAME_1 = "fanout_queue_1";
    String FAN_OUT_QUEUE_NAME_2 = "fanout_queue_2";
    String FAN_OUT_EXCHANGE = "fanout_exchange";
}

4》、调用接口,发送消息

@RestController
@RequestMapping("/fanout")
public class FanoutController {

    @Autowired
    private FanoutProducer fanoutProducer;

    @RequestMapping("/sendMsg")
    public String sendMsg() {
        fanoutProducer.sendMsg();
        return "FAN-OUT-QUEUE";
    }
}

2.2 消费者

@Component
public class FanoutConsumer {

    @RabbitListener(queues = {"fanout_queue_1"})
    public void receive(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息1:" + new String(message.getBody()));
    }

    @RabbitListener(queues = {"fanout_queue_2"})
    public void receive2(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息2:" + new String(message.getBody()));
    }
}

3. 路由模式 Direct Queue

路由模式 = 发布/订阅模式 + 指定 RoutingKey

3.1 生产者

1》、配置队列、交换机、队列与交换机之间的关系

@Configuration
public class DirectQueueConfig {

    // 声明队列
    @Bean
    public Queue directQueue1() {
        return new Queue(RabbitMqConstant.DIRECT_QUEUE_NAME_1);
    }

    @Bean
    public Queue directQueue2() {
        return new Queue(RabbitMqConstant.DIRECT_QUEUE_NAME_2);
    }

    // 声明交换机
    @Bean
    public DirectExchange exchange() {
        return new DirectExchange(RabbitMqConstant.DIRECT_EXCHANGE);
    }

    // 声明交换机与队列之间的关系
    @Bean
    public Binding bindingDirectQueue1(Queue directQueue1, DirectExchange exchange) {
        return BindingBuilder.bind(directQueue1).to(exchange).with(RabbitMqConstant.DIRECT_ROUTING_KEY_1);
    }

    @Bean
    public Binding bindingDirectQueue2(Queue directQueue2, DirectExchange exchange) {
        return BindingBuilder.bind(directQueue2).to(exchange).with(RabbitMqConstant.DIRECT_ROUTING_KEY_2);
    }
}

2》、发送消息

注意:这里是往交换机中发送消息

@Component
public class DirectProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMsgA() {
        for (int i = 0; i < 10; i++) {
            String msg = "路由模式下的消息 " + i;
            rabbitTemplate.convertAndSend(RabbitMqConstant.DIRECT_EXCHANGE, RabbitMqConstant.DIRECT_ROUTING_KEY_1, msg);
        }
    }

    public void sendMsgB() {
        for (int i = 0; i < 10; i++) {
            String msg = "路由模式下的消息 " + i;
            rabbitTemplate.convertAndSend(RabbitMqConstant.DIRECT_EXCHANGE, RabbitMqConstant.DIRECT_ROUTING_KEY_2, msg);
        }
    }
}

3》、常量类

public interface RabbitMqConstant {
    // simple
    String SIMPLE_QUEUE_NAME = "simple_queue";

    // work
    String WORK_QUEUE_NAME = "work_queue";

    // fanout
    String FAN_OUT_QUEUE_NAME_1 = "fanout_queue_1";
    String FAN_OUT_QUEUE_NAME_2 = "fanout_queue_2";
    String FAN_OUT_EXCHANGE = "fanout_exchange";

    // direct
    String DIRECT_QUEUE_NAME_1 = "direct_queue_1";
    String DIRECT_QUEUE_NAME_2 = "direct_queue_2";
    String DIRECT_EXCHANGE = "direct_exchange";
    String DIRECT_ROUTING_KEY_1 = "direct_add";
    String DIRECT_ROUTING_KEY_2 = "direct_update";
}

4》、调用接口,发送消息

@RestController
@RequestMapping("/direct")
public class DirectController {

    @Autowired
    private DirectProducer directProducer;

    @RequestMapping("/sendMsgA")
    public String sendMsgA() {
        directProducer.sendMsgA();
        return "DIRECT-QUEUE";
    }

    @RequestMapping("/sendMsgB")
    public String sendMsgB() {
        directProducer.sendMsgB();
        return "DIRECT-QUEUE";
    }
}

3.2 消费者

@Component
public class DirectConsumer {

    @RabbitListener(queues = {"direct_queue_1"})
    public void receive(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息1:" + new String(message.getBody()));
    }

    @RabbitListener(queues = {"direct_queue_2"})
    public void receive2(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息2:" + new String(message.getBody()));
    }
}

4. 主题模式 Topic Queue

4.1 生产者

1》、配置队列、交换机、队列与交换机之间的关系

@Configuration
public class TopicQueueConfig {

    // 声明队列
    @Bean
    public Queue topicQueue1() {
        return new Queue(RabbitMqConstant.TPOIC_QUEUE_NAME_1);
    }

    @Bean
    public Queue topicQueue2() {
        return new Queue(RabbitMqConstant.TPOIC_QUEUE_NAME_2);
    }

    // 声明交换机
    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(RabbitMqConstant.TOPIC_EXCHANGE);
    }

    // 声明交换机与队列之间的关系
    @Bean
    public Binding bindingDirectQueue1(Queue topicQueue1, TopicExchange exchange) {
        return BindingBuilder.bind(topicQueue1).to(exchange).with(RabbitMqConstant.TOPIC_ROUTING_KEY_1);
    }

    /**
    *
    * 功能描述:
    * *:匹配不多不少一个词   #:匹配一个或多个词
    *
    * @param topicQueue2
    * @param exchange
    */
    @Bean
    public Binding bindingDirectQueue2(Queue topicQueue2, TopicExchange exchange) {
        return BindingBuilder.bind(topicQueue2).to(exchange).with(RabbitMqConstant.TOPIC_ROUTING_KEY_2);
    }

2》、发送消息

注意:这里是往交换机中发送消息

@Component
public class TopicProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMsgA() {
        for (int i = 0; i < 10; i++) {
            String msg = "通配符模式--routingKey=topic.key消息 " + i;
            rabbitTemplate.convertAndSend(RabbitMqConstant.TOPIC_EXCHANGE, RabbitMqConstant.TOPIC_ROUTING_KEY_1, msg);
        }
    }

    public void sendMsgB() {
        for (int i = 0; i < 10; i++) {
            String msg = "通配符模式--routingKey=topic.#消息 " + i;
            rabbitTemplate.convertAndSend(RabbitMqConstant.TOPIC_EXCHANGE, RabbitMqConstant.TOPIC_ROUTING_KEY_3, msg);
        }
    }
}

3》、常量类

public interface RabbitMqConstant {
    // simple
    String SIMPLE_QUEUE_NAME = "simple_queue";

    // work
    String WORK_QUEUE_NAME = "work_queue";

    // fanout
    String FAN_OUT_QUEUE_NAME_1 = "fanout_queue_1";
    String FAN_OUT_QUEUE_NAME_2 = "fanout_queue_2";
    String FAN_OUT_EXCHANGE = "fanout_exchange";

   // direct
    String DIRECT_QUEUE_NAME_1 = "direct_queue_1";
    String DIRECT_QUEUE_NAME_2 = "direct_queue_2";
    String DIRECT_EXCHANGE = "direct_exchange";
    String DIRECT_ROUTING_KEY_1 = "direct_add";
    String DIRECT_ROUTING_KEY_2 = "direct_update";

    // topic
    String TPOIC_QUEUE_NAME_1 = "topic_queue_1";
    String TPOIC_QUEUE_NAME_2 = "topic_queue_2";
    String TOPIC_EXCHANGE = "topic_exchange";
    String TOPIC_ROUTING_KEY_1 = "topic.key";
    String TOPIC_ROUTING_KEY_2 = "topic.#";
    String TOPIC_ROUTING_KEY_3 = "topic.key2.key3";
}

4》、调用接口,发送消息

@RestController
@RequestMapping("/topic")
public class TopicController {

    @Autowired
    private TopicProducer topicProducer;

    @RequestMapping("/sendMsgA")
    public String sendMsgA() {
        topicProducer.sendMsgA();
        return "TOPIC-QUEUE";
    }

    @RequestMapping("/sendMsgB")
    public String sendMsgB() {
        topicProducer.sendMsgB();
        return "TOPIC-QUEUE";
    }
}

4.2 消费者

@Component
public class TopicConsumer {

    @RabbitListener(queues = {"topic_queue_1"})
    public void receive(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息1:" + new String(message.getBody()));
    }

    @RabbitListener(queues = {"topic_queue_2"})
    public void receive2(Message message, Channel channel) throws Exception{
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        System.out.println("我是消费信息2:" + new String(message.getBody()));
    }
    
}
SpringBoot集成RabbitMQ可以通过以下步骤实现。首先,在配置文件中添加RabbitMQ的连接信息。例如,在application.yml文件中配置RabbitMQ的主机、端口、用户名和密码等信息。\[1\]然后,引入SpringBoot整合RabbitMQ的依赖,包括spring-boot-starter-amqp和spring-rabbit-test等依赖项。\[2\]接下来,可以编写代码来实现与RabbitMQ的交互,例如发送和接收消息等操作。通过使用RabbitTemplate和@RabbitListener等注解,可以方便地实现消息的发送和接收。最后,可以通过运行SpringBoot应用程序来测试RabbitMQ集成是否成功。 #### 引用[.reference_title] - *1* [SpringBoot 集成RabbitMQ](https://blog.csdn.net/July_whj/article/details/120634833)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Springboot整合RabbitMQ](https://blog.csdn.net/weixin_49076273/article/details/124991012)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [SpringBoot教程(十五) | SpringBoot集成RabbitMq](https://blog.csdn.net/lsqingfeng/article/details/123652520)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值