SpringBoot 整合 RabbitMQ:和这只“兔子”交朋友

简介: RabbitMQ 就像是一个超级邮差兔,不过它不送胡萝卜,专门传递消息!交换机(Exchange),队列(Queue),路由键(Routing Key),消息(Message)。

大家好,我是小悟。

第一章:认识 RabbitMQ —— 不是普通的兔子!

RabbitMQ 就像是一个超级邮差兔,不过它不送胡萝卜,专门传递消息!想象一下:

  • 🏢 交换机(Exchange):邮局的分拣中心,负责把信件分到正确的路线
  • 📮 队列(Queue:你的专属邮箱,消息就在这里等你来取
  • 🏷️ 路由键(Routing Key:信封上的地址标签
  • 📦 消息(Message):你要传递的包裹(可以是任何数据)

这只“兔子”有四种工作模式:

  1. Hello World 模式:简单直接,像扔飞盘一样
  2. Work Queues 模式:多个工人抢活干,卷起来了!
  3. Publish/Subscribe 模式:广播模式,一人说话全村听见
  4. Routing & Topics 模式:智能分发,精准投喂

第二章:搭建“胡萝卜农场” —— 环境准备

2.1 安装 RabbitMQ

# 用 Docker 快速召唤兔子
docker run -d \
  --name rabbitmq \
  -p 5672:5672 \
  -p 15672:15672 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=admin123 \
  rabbitmq:management
# 访问管理界面:http://localhost:15672
# 账号:admin / 密码:admin123

2.2 创建 SpringBoot 项目

<!-- pom.xml 添加“兔粮” -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

第三章:配置“兔子窝” —— 连接设置

# application.yml
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: admin123
    # 虚拟主机,相当于兔子的公寓号
    virtual-host: /
    # 开启消息确认(确保兔子没偷吃消息)
    publisher-confirm-type: correlated
    publisher-returns: true
    listener:
      simple:
        # 手动确认消息(收到要说谢谢哦)
        acknowledge-mode: manual
        # 并发消费者数量(几只兔子一起干活)
        concurrency: 3
        max-concurrency: 10

第四章:定义“胡萝卜传输协议” —— 配置类

@Configuration
public class RabbitConfig {
    
    // 定义一个队列 - 就像给兔子一个收件箱
    @Bean
    public Queue carrotQueue() {
        // durable: true 表示兔子重启后队列还在(持久化)
        return new Queue("carrot.queue", true);
    }
    
    // 再定义一个队列,用来放烂掉的胡萝卜
    @Bean
    public Queue deadCarrotQueue() {
        return new Queue("dead.carrot.queue", true);
    }
    
    // 定义一个直连交换机 - 最简单的邮局
    @Bean
    public DirectExchange carrotExchange() {
        return new DirectExchange("carrot.exchange", true, false);
    }
    
    // 绑定队列和交换机(告诉兔子哪个邮箱放哪条路)
    @Bean
    public Binding bindCarrot() {
        return BindingBuilder.bind(carrotQueue())
                .to(carrotExchange())
                .with("carrot.routing.key"); // 路由键
    }
    
    // JSON 消息转换器(把胡萝卜包装成标准快递盒)
    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    
    // 死信队列配置(处理那些没人要的胡萝卜)
    @Bean
    public Queue carrotQueueWithDLX() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", "dead.letter.exchange");
        args.put("x-dead-letter-routing-key", "dead.carrot");
        return new Queue("carrot.with.dlx", true, false, false, args);
    }
}

第五章:“种胡萝卜” —— 生产者代码

@Component
@Slf4j
public class CarrotProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    /**
     * 发送一根普通胡萝卜
     */
    public void sendFreshCarrot(String message) {
        log.info("发射一根新鲜胡萝卜: {}", message);
        
        // 确保消息持久化(放冰箱保存)
        MessageProperties props = MessagePropertiesBuilder.newInstance()
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .build();
        
        Message msg = new Message(message.getBytes(), props);
        
        rabbitTemplate.convertAndSend(
            "carrot.exchange",
            "carrot.routing.key",
            msg,
            new CorrelationData(UUID.randomUUID().toString())
        );
        
        log.info("胡萝卜已交给兔子快递员");
    }
    
    /**
     * 发送一根 JSON 格式的豪华胡萝卜
     */
    public void sendLuxuryCarrot(CarrotDTO carrot) {
        log.info("准备发送豪华胡萝卜: {}", carrot);
        
        // 设置回调(确认兔子收到没)
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("兔子确认收到豪华胡萝卜,ID: {}", correlationData.getId());
            } else {
                log.error("兔子拒收豪华胡萝卜!原因: {}", cause);
            }
        });
        
        rabbitTemplate.convertAndSend(
            "carrot.exchange",
            "carrot.routing.key",
            carrot
        );
    }
    
    /**
     * 发送延迟胡萝卜(10秒后才送达)
     */
    public void sendDelayedCarrot(String message, int delaySeconds) {
        log.info("设置延迟胡萝卜,{}秒后送达: {}", delaySeconds, message);
        
        rabbitTemplate.convertAndSend(
            "delay.exchange",
            "delay.key",
            message,
            msg -> {
                msg.getMessageProperties().setDelay(delaySeconds * 1000);
                return msg;
            }
        );
    }
}
// 胡萝卜数据传输对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class CarrotDTO {
    private String color;
    private Integer weight;
    private Date harvestTime;
    private List<String> vitamins;
}

第六章:“吃胡萝卜” —— 消费者代码

@Component
@Slf4j
public class CarrotConsumer {
    
    /**
     * 处理新鲜胡萝卜 - 自动确认版
     */
    @RabbitListener(queues = "carrot.queue")
    public void eatFreshCarrot(String message) {
        log.info("兔子正在啃胡萝卜: {}", message);
        // 模拟吃胡萝卜的过程
        try {
            Thread.sleep(1000);
            log.info("真香!胡萝卜吃完了");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 处理豪华胡萝卜 - 手动确认版
     */
    @RabbitListener(queues = "luxury.carrot.queue")
    public void eatLuxuryCarrot(Message message, Channel channel, 
                               @Payload CarrotDTO carrot) {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        
        try {
            log.info("收到豪华胡萝卜!颜色: {}, 重量: {}g", 
                    carrot.getColor(), carrot.getWeight());
            
            // 模拟复杂的处理逻辑
            processLuxuryCarrot(carrot);
            
            // 手动确认(告诉兔子:我吃完了,你可以送下一个了)
            channel.basicAck(deliveryTag, false);
            log.info("豪华胡萝卜处理完成,已确认");
            
        } catch (Exception e) {
            log.error("吃豪华胡萝卜时噎住了: {}", e.getMessage());
            
            try {
                // 处理失败,拒绝消息(可以设置重新入队或丢弃)
                channel.basicNack(deliveryTag, false, true); // 重新入队
                // channel.basicReject(deliveryTag, false); // 直接丢弃
            } catch (IOException ioException) {
                log.error("无法拒绝消息: {}", ioException.getMessage());
            }
        }
    }
    
    /**
     * 批量吃胡萝卜(提高效率)
     */
    @RabbitListener(queues = "batch.carrot.queue", 
                   containerFactory = "batchFactory")
    public void eatBatchCarrot(List<Message> messages, Channel channel) {
        log.info("收到一批胡萝卜,共{}根", messages.size());
        
        for (Message message : messages) {
            try {
                String carrot = new String(message.getBody());
                log.info("正在处理胡萝卜: {}", carrot);
                // 批量确认
                channel.basicAck(message.getMessageProperties()
                    .getDeliveryTag(), false);
            } catch (Exception e) {
                log.error("处理失败: {}", e.getMessage());
            }
        }
    }
    
    private void processLuxuryCarrot(CarrotDTO carrot) {
        // 复杂的业务逻辑
        log.info("分析胡萝卜营养成分...");
        log.info("维生素含量: {}", carrot.getVitamins());
        // 这里可以添加数据库操作、调用其他服务等
    }
}

第七章:特殊场景处理

7.1 死信队列配置

@Configuration
public class DeadLetterConfig {
    
    @Bean
    public DirectExchange deadLetterExchange() {
        return new DirectExchange("dead.letter.exchange");
    }
    
    @Bean
    public Queue deadLetterQueue() {
        return new Queue("dead.letter.queue");
    }
    
    @Bean
    public Binding deadLetterBinding() {
        return BindingBuilder.bind(deadLetterQueue())
                .to(deadLetterExchange())
                .with("dead.carrot");
    }
    
    /**
     * 监听死信队列
     */
    @Component
    @Slf4j
    public class DeadLetterConsumer {
        @RabbitListener(queues = "dead.letter.queue")
        public void handleDeadLetter(String message) {
            log.warn("收到死信胡萝卜,需要人工处理: {}", message);
            // 可以发送告警邮件、记录日志等
        }
    }
}

7.2 延迟队列(定时任务)

@Configuration
public class DelayConfig {
    
    @Bean
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange("delay.exchange", 
                "x-delayed-message", true, false, args);
    }
    
    @Bean
    public Queue delayQueue() {
        return new Queue("delay.queue");
    }
    
    @Bean
    public Binding delayBinding() {
        return BindingBuilder.bind(delayQueue())
                .to(delayExchange())
                .with("delay.key")
                .noargs();
    }
}

第八章:测试我们的“兔子农场”

@SpringBootTest
@Slf4j
class RabbitmqTest {
    
    @Autowired
    private CarrotProducer carrotProducer;
    
    @Test
    void testSendCarrot() {
        // 测试发送普通胡萝卜
        carrotProducer.sendFreshCarrot("我是新鲜的胡萝卜!");
        
        // 测试发送豪华胡萝卜
        CarrotDTO luxuryCarrot = new CarrotDTO(
            "橙色",
            200,
            new Date(),
            Arrays.asList("维生素A", "维生素C", "胡萝卜素")
        );
        carrotProducer.sendLuxuryCarrot(luxuryCarrot);
        
        // 测试延迟胡萝卜
        carrotProducer.sendDelayedCarrot("我是10秒后的胡萝卜", 10);
        
        log.info("所有胡萝卜已发送,请观察兔子们的表现!");
    }
    
    @Test
    void testMassProduction() {
        // 批量生产胡萝卜,测试性能
        for (int i = 1; i <= 100; i++) {
            carrotProducer.sendFreshCarrot("批量胡萝卜#" + i);
        }
        log.info("100根胡萝卜已投入生产线!");
    }
}

第九章:监控和运维

9.1 健康检查

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,rabbit
  endpoint:
    health:
      show-details: always

9.2 自定义监控

@Component
public class RabbitMonitor {
    
    @Autowired
    private RabbitAdmin rabbitAdmin;
    
    public void checkRabbitHealth() {
        Properties queueProperties = rabbitAdmin.getQueueProperties("carrot.queue");
        if (queueProperties != null) {
            int messageCount = Integer.parseInt(
                queueProperties.get("QUEUE_MESSAGE_COUNT").toString()
            );
            log.info("胡萝卜队列当前有 {} 根胡萝卜等待处理", messageCount);
        }
    }
    
    /**
     * 定期清理积压消息
     */
    @Scheduled(fixedDelay = 60000) // 每分钟检查一次
    public void clearBacklog() {
        // 实现清理逻辑
        log.info("正在打扫兔子窝...");
    }
}

第十章:总结 —— 和兔子相处的秘诀

学到了什么:

  1. RabbitMQ 是个好邮差:可靠、灵活、功能强大的消息中间件
  2. SpringBoot 是兔子的好朋友:通过简单的配置就能轻松集成
  3. 消息确认很重要:别让胡萝卜在半路丢了
  4. 死信队列是保险箱:处理异常情况的最佳实践
  5. 延迟消息很实用:实现定时任务的好方法

实践建议:

  1. 给消息上保险:总是开启消息持久化和确认机制
  2. 合理设置TTL:别让胡萝卜放太久烂掉了
  3. 监控不能少:时刻关注兔子的健康状况
  4. 错误处理要优雅:准备好处理各种异常情况
  5. 性能要平衡:消费者数量不是越多越好

学习方向:

  1. 集群部署:养一群兔子,避免单点故障
  2. 镜像队列:给胡萝卜做备份
  3. 优先级队列:VIP 胡萝卜优先处理
  4. 流控机制:别把兔子撑坏了
  5. 与其他组件集成:让兔子和别的动物(其他中间件)合作

结尾:

记住,RabbitMQ 就像一只训练有素的邮差兔:

  • 发送消息,它接收
  • 发布消息,它路由
  • 消费消息,它确认
  • 搞砸了,它死信

只要遵循 RabbitMQ 的“兔子法则”,你的消息系统就会像兔子繁殖一样——快速、可靠、生生不息!

最后:虽然 RabbitMQ 很可爱,但请不要真的喂它胡萝卜,它只吃 0 和 1(二进制数据)!


代码仓库建议结构:

rabbitmq-demo/
├── src/main/java/com/example/rabbitmq/
│   ├── config/          # 配置类
│   ├── producer/        # 生产者
│   ├── consumer/        # 消费者
│   ├── dto/            # 数据传输对象
│   └── RabbitmqDemoApplication.java
├── src/main/resources/
│   └── application.yml
└── pom.xml

现在就去和你的 RabbitMQ 兔子做好朋友吧!记得每天喂它足够的消息,但别把它撑着了哦~

SpringBoot 整合 RabbitMQ:和这只“兔子”交朋友.png

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。


您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

相关文章
|
6天前
|
人工智能 安全 API
CoPaw:5分钟部署你的 AI助理
源自阿里巴巴开源生态的个人 AI 助理——CoPaw。作为阿里倾力打造的开源力作,CoPaw 完美打通钉钉、飞书、Discord 等多平台对话通道,支持定时任务自动化。内置 PDF/Office 深度处理、新闻摘要等强大技能,更开放自定义扩展接口。坚持数据全程私有化部署,绝不上传云端,让每一位用户都能在大厂技术加持下,拥有安全、专属的智能助手。
|
9天前
|
人工智能 自然语言处理 JavaScript
2026年Windows+Ollama本地部署OpenClaw保姆级教程:本地AI Agent+阿里云上快速搭建
2026年OpenClaw凭借本地部署、私有化运行的特性,成为打造个人智能体的核心工具,而Ollama作为轻量级本地大模型管理工具,能让OpenClaw摆脱对云端大模型的依赖,实现**本地推理、数据不泄露、全流程私有化**的智能体验。本文基于Windows 11系统,从硬件环境准备、Ollama安装与模型定制、OpenClaw部署配置、技能扩展到常见问题排查,打造保姆级本地部署教程,同时补充阿里云OpenClaw(Clawdbot)快速部署步骤,兼顾本地私有化需求与云端7×24小时运行需求,文中所有代码命令均可直接复制执行,确保零基础用户也能快速搭建属于自己的本地智能体。
9897 78
|
6天前
|
人工智能 安全 JavaScript
阿里云上+本地部署OpenClaw(小龙虾)新手攻略:解锁10大必备Skills,零基础也能玩转AI助手
2026年,开源AI代理工具OpenClaw(昵称“小龙虾”)凭借“能实际做事”的核心优势,在GitHub斩获25万+星标,成为现象级AI工具。它最强大的魅力在于可扩展的Skills(技能包)系统——通过ClawHub插件市场的数百个技能,能让AI助手从简单聊天升级为处理办公、学习、日常事务的全能帮手。
5415 14
|
7天前
|
人工智能 自然语言处理 机器人
保姆级教程:Mac本地搭建OpenClaw及阿里云上1分钟部署OpenClaw+飞书集成实战指南
OpenClaw(曾用名Clawdbot、Moltbot)作为2026年最热门的开源个人AI助手平台,以“自然语言驱动自动化”为核心,支持对接飞书、Telegram等主流通讯工具,可替代人工完成文件操作、日历管理、邮件处理等重复性工作。其模块化架构适配多系统环境,既可以在Mac上本地化部署打造私人助手,也能通过阿里云实现7×24小时稳定运行,完美兼顾隐私性与便捷性。
5401 12
|
9天前
|
人工智能 JSON JavaScript
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
手把手教你用 OpenClaw(v2026.2.22-2)+ 飞书,10分钟零代码搭建专属AI机器人!内置飞书插件,无需额外安装;支持Claude等主流模型,命令行一键配置。告别复杂开发,像聊同事一样自然对话。
5691 14
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
|
4天前
|
人工智能 JavaScript Ubuntu
5分钟上手龙虾AI!OpenClaw部署(阿里云+本地)+ 免费多模型配置保姆级教程(MiniMax、Claude、阿里云百炼)
OpenClaw(昵称“龙虾AI”)作为2026年热门的开源个人AI助手,由PSPDFKit创始人Peter Steinberger开发,核心优势在于“真正执行任务”——不仅能聊天互动,还能自动处理邮件、管理日程、订机票、写代码等,且所有数据本地处理,隐私完全可控。它支持接入MiniMax、Claude、GPT等多类大模型,兼容微信、Telegram、飞书等主流聊天工具,搭配100+可扩展技能,成为兼顾实用性与隐私性的AI工具首选。
2906 6
|
2天前
|
人工智能 JavaScript 测试技术
保姆级教程:OpenClaw阿里云及本地部署+Claude Code集成,打造全能 AI 编程助手
在AI编程工具百花齐放的2026年,Anthropic推出的Claude Code凭借72.5%的SWE-bench测试高分、25倍于GitHub Copilot的上下文窗口,成为开发者追捧的智能编程助手。但单一工具仍有局限——Claude Code擅长代码生成与审查,却缺乏灵活的部署与自动化执行能力;而OpenClaw(前身为Clawdbot)作为开源AI代理框架,能完美弥补这一短板,通过云端与本地双部署,实现“代码开发-测试-部署”全流程自动化。
1506 13
|
4天前
|
人工智能 JavaScript API
阿里云及本地 Windows 部署(OpenClaw+Ollama)保姆级教程及技能扩展与问题排查
OpenClaw(原Clawdbot)作为2026年主流的开源AI智能体工具,具备系统级操作权限,能将自然语言指令转化为文件操作、程序控制等实际行为。搭配轻量级本地大模型管理工具Ollama,可实现本地推理、数据私有化存储的全闭环;而阿里云提供的云端部署方案,则能满足7×24小时稳定运行需求。本文将详细拆解2026年阿里云与本地(Windows 11系统)部署OpenClaw的完整流程,包含Ollama模型定制、技能扩展及常见问题排查,所有代码命令可直接复制执行,零基础用户也能快速上手。
1856 3

热门文章

最新文章