SpringBoot整合RabbitMQ

发布订阅模式

必须先配置一 个fanout类型的交换器,不需要指定对应的路由 键(Routing key),同时会将消息路由到每一 个消息队列上,然后每个消息队列都可以对相同 的消息进行接收存储,进而由各自消息队列关联 的消费者进行消费

- 添加依赖,在SpriingBoot项目中的pom.xml中加入RabbitMQ相关依赖,以便使用RabbitMQ功能

xml 复制代码
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

- 在application.properties中配置RabbitMQ连接信息,包括RabbitMQ的地址、端口、用户名、密码等基本信息

ini 复制代码
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.publisher-confirm-type=simple
simple模式表示使用简单的确认模式,当消息被成功处理后,RabbitMQ 会发送一个确认信号。这个配置能够帮助开发者确认消息是否已经成功发布。
spring.rabbitmq.listener.simple.concurrency=3
该配置项用于配置监听器的最小并发数。意思是启动时至少会有 3 个消费者线程来处理 RabbitMQ 队列中的消息。
spring.rabbitmq.listener.simple.max-concurrency=10
该配置项用于设置监听器的最大并发数。意思是监听器可以在负载较高时,最多同时启动 10 个消费者线程来消费消息

- 创建连接工厂(RabbitConnectionFactoryBean)

ConnectionFactory 是 RabbitMQ 连接的核心,它负责创建与 RabbitMQ 服务器的连接。Spring Boot 自动配置了 ConnectionFactory,因此通常不需要手动创建连接工厂。

RabbitTemplate 是 Spring AMQP 用来发送消息的核心类。Spring Boot 会自动配置一个 RabbitTemplate

@RabbitListener 注解来监听 RabbitMQ 消息队列,Spring Boot 会自动配置 RabbitListenerContainerFactory

如果需要更多的自定义配置,可以通过 RabbitConnectionFactoryBean 或者 ConnectionFactory 接口手动配置连接工厂,并在配置类中将其作为 @Bean 注入。

- 定义交换机、队列、绑定: 创建 RabbitMQ 交换机(Exchange)、队列(Queue)和它们之间的绑定(Binding)。

typescript 复制代码
AmqpAdmin管理类配置方法
package com.xyu;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
@SpringBootTest
class SpringbootXyuProjectApplicationTests {
    @Autowired
    public AmqpAdmin amqpAdmin;
    @Test
    void contextLoads() {
    }
    @Test
    public void amqpAdmin(){
        amqpAdmin.declareExchange(new FanoutExchange("fanout_exchange"));
//        定义一个交换机
        amqpAdmin.declareQueue(new Queue("fanout_queue_email"));
        amqpAdmin.declareQueue(new Queue("fanout_queue_sms"));
//        绑定
        amqpAdmin.declareBinding(new Binding(
                "fanout_queue_email",            // 绑定的目标队列名称
                Binding.DestinationType.QUEUE,    // 目标类型是队列
                "fanout_exchange",               // 交换机的名称
                "",                              // 对于 Fanout 交换机,路由键为空字符串
                null                             // 附加参数,通常用于更高级的绑定配置,当前没有使用
        ));
        amqpAdmin.declareBinding(new Binding(
                "fanout_queue_sms",            // 绑定的目标队列名称
                Binding.DestinationType.QUEUE,    // 目标类型是队列
                "fanout_exchange",               // 交换机的名称
                "",                              // 对于 Fanout 交换机,路由键为空字符串
                null                             // 附加参数,通常用于更高级的绑定配置,当前没有使用
        ));
    }
}

- 消息发送: 使用 RabbitTemplate 来发送消息。通过 RabbitTemplateconvertAndSend 方法发送消息到指定的交换机、路由键等

  1. 创建实体类,发送信息
arduino 复制代码
/*
 * Copyright 2013-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xyu.po;
/**
 * @author <a href="mailto:[email protected]">theonefx</a>
 */
public class User {
    private String name;
    private Integer age;
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

2.序列化(将实体类实现JDK自带的Serializable序列化接口--对结果进行加密. 定制其他类型的消息转换器)

jackson转换器

kotlin 复制代码
package com.xyu.Config;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
 @Bean
 public MessageConverter messageConverter(){
 return new Jackson2JsonMessageConverter();
 }
}

将 Java 对象转换为 JSON 字符串。这个过程通常用于将 Java 对象存储为 JSON 格式(比如用于 API 返回数据、文件保存等)

3.传入数据

java 复制代码
@Test
public void Publisher(){
    User user = new User();
    user.setAge(18);
    user.setName("天天");
    rabbitTemplate.convertAndSend("fanout_exchange","",user);
}

效果:

- 消息监听: 使用 @RabbitListener 注解来标记消息接收方法,Spring Boot 会自动监听队列中的消息,并调用相应的方法处理消息。

ini 复制代码
package com.xyu.Service;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class RabbitMqListenerService {
 @RabbitListener(queues = "fanout_queue_email")
 public void psubConsumerEmail(Message message) {
 byte[] body = message.getBody();
 String s = new String(body);
 System.out.println("邮件业务接收到消息: "+s);
 }
 @RabbitListener(queues = "fanout_queue_sms")
 public void psubConsumerSms(Message message) {
  byte[] body = message.getBody();
  String s = new String(body);
  System.out.println("短信业务接收到消息: " + s);
 }
}

基于配置类的方式(创建两个不同的交换机)

配置交换机

typescript 复制代码
package com.xyu.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.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableRabbit
//@EnableRabbit‌注解在Spring Boot应用中用于启用基于注解的RabbitMQ消息处理功能。
public class RabbitMQConfig {
   @Bean
   public FanoutExchange fanoutExchange() {
    return new FanoutExchange("exchange_my");
   }
    // 定义不同名称的消息队列
    @Bean
    public Queue smsQueue() {
        return new Queue("fanout_queue_tem", true);  // 队列持久化
    }

    @Bean
    public Queue emailQueue() {
        return new Queue("fanout_queue_num", true);  // 队列持久化
    }

    // 将消息队列与交换器绑定
    @Bean
    public Binding smsBinding() {
        return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding emailBinding() {
        return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
    }

   @Bean
   public MessageConverter messageConverter(){
 return new Jackson2JsonMessageConverter();
 }
}

接受信息

less 复制代码
@RabbitListener(bindings =@QueueBinding(value =
@Queue("fanout_queue_tem"), exchange =
@Exchange(value = "exchange_my"
        ,type = "fanout")))
public void psubConsumerEmailAno(User user) {
 System.out.println("1邮件业务接收到消息: "+user);
}
@RabbitListener(bindings =@QueueBinding(value =
@Queue("fanout_queue_num"),exchange =
@Exchange(value = "exchange_my"
        ,type = "fanout")))
public void psubConsumerSmsAno(User user) {
 System.out.println("1短信业务接收到消息: "+user);
}

发送信息

sql 复制代码
@Test
public void Publisher(){
    User user = new User();
    user.setAge(18);
    user.setName("天天1");
    rabbitTemplate.convertAndSend("fanout_exchange","",user);
    rabbitTemplate.convertAndSend("exchange_my","",user);
}

效果展示

Routing(路由模式)

在Routing工作模式中,必须先配置一个direct类 型的交换器,并指定不同的路由键值(Routing key)将对应的消息从交换器路由到不同的消息 队列进行存储,由消费者进行各自消费。

  • FanoutExchange 是一种专门用于广播消息的交换机类型,它不需要绑定 type="direct",因为 FanoutExchange 本身就是一种无条件广播的交换机类型。
  • 使用 direct 类型的交换机,那应该使用 DirectExchange
typescript 复制代码
 //路由
    @Bean
    public DirectExchange directExchange(){
       return new DirectExchange("routing_exchange");
    }
    @Bean
    public Queue routeQueue(){
       return new Queue("routing_queue_all",true);
    }
    @Bean
    public Binding routeBinding(){return BindingBuilder.bind(routeQueue()).to(directExchange()).withQueueName();}

}
typescript 复制代码
存数据
@Test
public void routingPublisher() {
    rabbitTemplate.convertAndSend("routing_exchange"
            ,
            "error_routing_key"
            ,
            "routing send error message");
}
less 复制代码
 @RabbitListener(bindings =@QueueBinding(value =
 @Queue("fanout_queue_num"),exchange =
 @Exchange(value = "exchange_my"
         ,type = "fanout")))
 public void psubConsumerSmsAno(User user) {
  System.out.println("1短信业务接收到消息: "+user);
 }
 @RabbitListener(
         bindings = @QueueBinding(
                 value = @Queue(name = "routing_queue_all"),
                 exchange = @Exchange(value = "routing_exchange", type = "direct"),
                 key = "error_routing_key")
 )
 public void routingConsumerError(String message) {
  System.out.println("接收到error级别日志消息: " + message);
 }
}

效果展示

Topics(通配符模式)

定义交换机和队列

typescript 复制代码
@Bean
public TopicExchange topicExchange(){
    return new TopicExchange("topic_exchange");
}
@Bean
public Queue topic_queue_email(){
   return new Queue("topic_queue_email",true);
}
@Bean
public BindingBuilder.TopicExchangeRoutingKeyConfigurer topicBinding(){return BindingBuilder.bind(topic_queue_email()).to(topicExchange());}

发数据

typescript 复制代码
   @Test
    public void topicPublisher() {
        rabbitTemplate.convertAndSend("topic_exchange"
                ,
                "info.email"
                ,
                "topics send email message");
        rabbitTemplate.convertAndSend("topic_exchange"
                ,
                "info.sms"
                ,
                "topics send sms message");
        rabbitTemplate.convertAndSend("topic_exchange"
                ,
                "info.email.sms"
                ,
                "topics send email and sms message");}


}

取数据

less 复制代码
 @RabbitListener(bindings =@QueueBinding(value =
 @Queue("topic_queue_email"),exchange =
 @Exchange(value = "topic_exchange"
         ,type = "topic"),
         key = "info.#.sms.#"))
 public void topicConsumerSms(String message) {
  System.out.println("接收到短信订阅需求处理消息: "+message);
 }
}

效果 :

相关推荐
十九万里4 分钟前
基于 OpenCV + Haar Cascade 实现的极简版本人脸标注(本地化)
人工智能·后端
我是谁的程序员12 分钟前
Flutter图片加载优化,自动缓存大小
后端
疯狂的程序猴13 分钟前
FlutterWeb实战:02-加载体验优化
后端
调试人生的显微镜16 分钟前
Flutter性能优化实践 —— UI篇
后端
用户77853718369621 分钟前
揭秘AI自动化框架Browser-use(四):Browser-use记忆模块技术解析
人工智能·后端
一个热爱生活的普通人27 分钟前
如何使用 Benchmark 编写高效的性能测试
后端·go
GoGeekBaird28 分钟前
基于 CAMEL-AI 🦉OWL框架的股票分析智能体
后端·github
东百牧码人29 分钟前
开源项目推荐:MasterNeverDown.LeetCode,刷题必备的C#利器
后端
SimonKing30 分钟前
JDK 24 新特性解析:更安全、更高效、更易用
java·后端·架构
helloworld_工程师30 分钟前
DeepSeek R1 集成难题完美解决:DeepSeek4j来帮你解决
前端·后端·github