☰
SpringBoot集成RabbitMQ极简Hello World教程:从Erlang安装到消息收发
2026/10/10 3:34:04 网站建设 项目流程

我第一次接触 RabbitMQ 的时候,第一反应就是先找一篇“SpringBoot 集成 RabbitMQ Hello World”的教程。结果翻了好几篇,要么开篇就甩一堆 AMQP 协议名词,要么就是版本互相打架,折腾半天连个“Hello World”都打印不出来。这篇文章就是我踩完这些坑之后的整理版:用 SpringBoot 写一个极简的 RabbitMQ Hello World,从 Erlang 安装、服务启动、生产端消费端代码,到网页管理台验证消息,一条线完整跑通。

整个教程适合刚接触消息队列、想先看一个真实例子跑起来的 Java 开发者,也适合照着旧教程装了半天、最后卡在版本或启动环节的人。你不用先精通交换机、路由、死信这些概念,只要跟着把这条路走通,消息队列最核心的那点事儿,基本就摸到门槛了。

1. 为什么第一个消息队列程序我推荐 Spring Boot 来写

1.1 从原生 Java 客户端的繁琐说起

很多老教程会先用原生 Java 客户端演示 Hello World,代码大概长这样:

ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { channel.queueDeclare("hello", false, false, false, null); channel.basicPublish("", "hello", null, "Hello World".getBytes()); }

看起来似乎也不长?但真正生产环境里,你还要处理连接的复用、断线重连、消息确认、消费者线程模型、序列化转换...这些代码要是全手写,Hello World 就不是十分钟能搞定的事了。

Spring Boot 的spring-boot-starter-amqp把这些基础设施全部做成了自动配置:连接工厂、RabbitTemplate、RabbitAdmin、消息监听容器,全都有现成的 Bean 可以直接注入。你要做的,就是在配置文件里写几个连接参数,然后往代码里丢一个RabbitTemplate发消息,再丢一个@RabbitListener注解收消息。

这也是我推荐用 SpringBoot 写第一个 RabbitMQ 程序的根本原因:你的精力应该放在理解消息队列的工作方式上,而不是浪费在手动关闭 Connection、创建 Channel 这些重复劳动上。

1.2 RabbitMQ 的简单消息模型:一条消息怎么走

在写代码之前,建议先花两分钟理解 RabbitMQ 的消息流转路径,否则后面很多配置你会不知道为什么这样填。

RabbitMQ 里最核心的两个概念是Exchange(交换器)和Queue(队列)。生产者的消息不是直接扔进队列的,而是先扔给 Exchange,再由 Exchange 根据路由规则投递到对应的 Queue,最后消费者从 Queue 里取消息。可以用一个生活化的场景来理解:

  • 生产者是发货的人
  • Exchange是快递分拣中心
  • Queue是小区楼下的快递柜
  • 消费者是取快递的住户

分拣中心按面单(Routing Key)决定把包裹放到几号快递柜(Queue)。

在 Hello World 阶段,我们用的是 RabbitMQ 内置的默认交换器。这个默认交换器有一个特别方便的特性:如果你发送消息时指定 Exchange 为空字符串,那么消息会被直接路由到 Routing Key 同名的队列。所以下面的代码:

rabbitTemplate.convertAndSend("", "hello", "你好 RabbitMQ");

就是在告诉 RabbitMQ:走默认交换器,放到名叫hello的队列里。这就是 Hello World 能写得极简的核心原因。

1.3 这套 Hello World 适合谁

说实话,只要你属于下面任意一种情况,这个教程你都可以无脑跟练:

  • 刚接触消息队列,想知道 RabbitMQ 到底怎么用、SpringBoot 怎么接的人
  • 项目里已经要引用 RabbitMQ,但不敢上手、怕把环境搞坏的人
  • 照着老教程做了,结果 SpringBoot 版本太高、RabbitMQ 启动失败,半天没跑通的人

另外提一句,如果你正在做基于 SpringBoot 的毕业设计或管理系统,通信模块想用消息队列做解耦,这篇内容也能给你打个底。后面你可以很自然地从 Hello World 延伸到 Exchange 绑定、延迟队列、死信队列这些进阶能力。

2. 环境准备:Erlang 与 RabbitMQ 的版本匹配最容易踩坑

2.1 安装前先定版本:Erlang 不是越新越好

很多新手在这步就翻车了。RabbitMQ 服务端是用 Erlang/OTP 编写的,所以装 RabbitMQ 之前必须先装 Erlang。但 Erlang 不是随手装个最新版就行的,RabbitMQ 和 Erlang 之间有严格的版本匹配关系。

这里有一张我实践中常用的对应参考表(以近几个版本为例):

RabbitMQ 版本最低 Erlang 版本推荐 Erlang 版本
3.13.x26.026.2.x
3.12.x25.025.3.x
3.11.x25.025.0.x
3.10.x23.224.3.x

我的建议是:如果完全没经验,优先选择RabbitMQ 3.13.x + Erlang 26.2.x的组合,或者直接去官网下载页面看官方给出的配套版本。装完了先用erl -version确认 Erlang 能正常输出版本号,再进行下一步。

这里我踩过一次很深的坑:当时本机有旧版 Erlang 没卸干净,新 RabbbitMQ 怎么都起不来,日志显示版本不兼容,最后把旧版 Erlang 彻底移除、重装配套版本才解决。所以安装前建议先检查一下环境里是否残留旧版本。

2.2 Windows 安装实操(含管理插件)

Windows 用户的操作流程大概是这样的:

先装 Erlang。到官网下载 OTP 安装包,一路 Next 安装。装完之后开一个命令行窗口,输入erl -version,能正常显示版本号说明 Erlang 就位了。

再装 RabbitMQ。去官网下载 Windows 安装包,安装完成后 RabbitMQ 会作为 Windows 服务自动注册并启动。强烈建议以管理员身份打开终端,进入 RabbitMQ 的 sbin 目录(一般在C:\Program Files\RabbitMQ Server\rabbitmq_server-3.13.x\sbin),执行:

rabbitmq-plugins enable rabbitmq_management

这一步是开启网页管理控制台,也就是很多人提到过的 RabbitMQ 网页操作界面。执行成功后访问http://localhost:15672,用默认账号guest/guest登录,看到控制台就算是装好了。

启动服务的方式有两种:一种是直接在 Windows 服务管理器里找到 RabbitMQ 并启动;另一种是用命令rabbitmq-service start。我一般喜欢用命令,因为能看到更明确的输出信息。

2.3 其他环境快速起服务:Linux / macOS / Docker

如果你用的是 Linux,以 Debian/Ubuntu 为例:

sudo apt install rabbitmq-server sudo systemctl enable rabbitmq-server sudo systemctl start rabbitmq-server sudo rabbitmq-plugins enable rabbitmq_management

macOS 用户用 Homebrew 会更简单:

brew install rabbitmq

安装完成后,RabbitMQ 的可执行文件在/opt/homebrew/opt/rabbitmq/sbin下,执行rabbitmq-server -detached在后台启动,再执行rabbitmq-plugins enable rabbitmq_management开启管理台。

如果你只是为了本地快速体验,Docker 是更省事的选择:

docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.13-management

注意这里镜像用的是带management标签的,自带管理插件。但我个人建议第一次入门还是在本机装一个原生服务,这样报错、看日志、理解运行机制都会更直观,Docker 等熟悉之后再玩也不迟。

2.4 启动成功之后先做三件事

环境装完先别急着写代码,花两分钟做三个验证:

第一,用rabbitmqctl status看服务运行状态,确认 nodes 节点正常;第二,打开http://localhost:15672,用guest/guest登录管理台;第三,确认 5672 端口(AMQP 协议端口)能被本地程序访问。Windows 下可以用netstat -ano | findstr "5672",Linux/macOS 下可以用lsof -i:5672或ss -tlnp | grep 5672。

这三个检查做完,环境基本就稳了。如果管理台登录不了或者服务启动失败,别急,第 5 章我会单独讲排查套路。

3. 工程搭建与配置:依赖只要一个,配置不到十行

3.1 依赖引入:一个 starter 就够

新建一个 Spring Boot 工程,注意版本。Spring Boot 2.x 和 3.x 在本文的集成方式上几乎没有差别,3.x 配合 JDK 17+ 实测没有任何问题。

Maven 项目在pom.xml里加入:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>

Gradle 项目对应的是:

implementation 'org.springframework.boot:spring-boot-starter-amqp'

这个 starter 会自动带出spring-rabbit和amqp-client依赖,并且版本由 SpringBoot 统一管理。你不需要手动指定这几个依赖的版本号,这正是很多人踩坑的地方——手动指定旧版 amqp-client 后,和 SpringBoot 的自动配置不兼容,报出一堆奇怪错误。

3.2 application.yml 最小配置

Spring Boot 集成 RabbitMQ 的连接参数全部以spring.rabbitmq.*开头。Hello World 阶段,下面这几行就够用:

spring: application: name: rabbitmq-hello rabbitmq: host: localhost port: 5672 username: guest password: guest

解释一下每个参数:

  • host和port:RabbitMQ 服务地址和 AMQP 端口,默认就是 localhost 和 5672。
  • username和password:连接用户名和密码,默认账号 guest/guest。
  • 虚拟主机virtual-host默认是/,所以不写也行。管理台里看到的默认 vhost 就是一个斜杠/。

这里强调一句:在你本机还没跑通之前,不要加上publisher-confirm-type、listener之类的进阶配置。那些是后面做消息确认、重试机制时才需要的,一开始加多了反而干扰排查。

如果你用的是多模块项目,把 RabbitMQ 相关代码独立成一个 module 是很自然的做法,Spring Boot 的自动配置依旧生效,不影响本文的任何步骤。

3.3 声明队列的两种常见方式

Hello World 用的队列叫hello,这个队列得先声明出来,生产者和消费者才能对上号。两种常用方式:

第一种,在配置类里声明一个 Queue Bean:

@Configuration @EnableRabbit public class RabbitConfig { @Bean public Queue helloQueue() { return new Queue("hello", false); } }

new Queue("hello", false)表示创建一个名为 hello 的非持久化队列。如果你想持久化,就改成new Queue("hello", true),或者用QueueBuilder.durable("hello").build()。

第二种,直接在@RabbitListener注解里声明:

@RabbitListener(queuesToDeclare = @Queue("hello")) public void receive(String message) { // ... }

这种方式更省事,但如果你之后要声明交换机或复杂绑定关系,还是第一种放在配置类里更灵活。我下面的示例主推第一种,因为它更符合实际项目的写法。

4. 第一个 Hello World:生产端、消费端、网页验证

4.1 生产者写起来有多简单

生产者端的核心对象是RabbitTemplate,Spring Boot 自动配置已经把它放到了容器里,直接用构造器注入进来就可以。

@RestController @RequestMapping("/api") public class HelloController { private final RabbitTemplate rabbitTemplate; public HelloController(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } @GetMapping("/send") public String send(@RequestParam(defaultValue = "Hello RabbitMQ!") String msg) { rabbitTemplate.convertAndSend("", "hello", msg); return "消息已发送: " + msg; } }

关键代码就一行:

rabbitTemplate.convertAndSend("", "hello", msg);

三个参数分别是 exchange、routingKey、消息内容。exchange 传空字符串就是使用默认交换器,消息会直接路由到名为hello的队列。convertAndSend这个名字里的 "convert" 很关键:RabbitTemplate 内置了消息转换器,会把 Java 对象转成字节数组发送。String 类型默认按 UTF-8 转字节,消费者那边直接拿 String 接收即可。

这里有个容易被忽略的点:RabbitTemplate 是线程安全的,可以放心注入到任何类里复用,千万不要每次发消息都 new 一个。Spring 容器管理好这一个实例就够了。

4.2 消费者:一个注解搞定监听

消费者端的核心是@RabbitListener注解,把监听方法直接绑定到队列上。

@Component public class HelloConsumer { private static final Logger log = LoggerFactory.getLogger(HelloConsumer.class); @RabbitListener(queues = "hello") public void onMessage(String message) { log.info("收到消息: {}", message); } }

只要 Spring 容器扫描到这个类,并且启用了 Rabbit 注解支持(也就是前面配置类里的@EnableRabbit),一旦hello队列有新消息进来,这个方法就会被自动调用。

这里有两个很容易踩的坑:

第一,别忘加@EnableRabbit。忘记加的话,@RabbitListener完全不会生效,消息发了也没反应。

第二,消费者类必须被 Spring 扫描到。如果项目包结构比较乱,消费者类放在了扫描路径之外,照样收不到消息。检查一下启动类所在包和你写的类包路径是否一致,这是最常见的低级错误。

补充一个进阶点:@RabbitListener默认使用自动确认模式,也就是方法正常返回就确认消息。如果方法抛出异常,消息会回到队列等待重投。Hello World 阶段用默认行为就够了,手动确认后面再研究。

4.3 跑起来的三种方式

代码写完后,有三种方式可以触发消息发送。

方式一:启动即自动发送。写一个CommandLineRunner,Spring Boot 启动完成后自动执行:

@Component public class HelloSenderRunner implements CommandLineRunner { private final RabbitTemplate rabbitTemplate; public HelloSenderRunner(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } @Override public void run(String... args) { rabbitTemplate.convertAndSend("", "hello", "Hello World from Spring Boot"); } }

这种方式非常适合第一次验证:启动应用,看控制台输出有没有“收到消息”的日志。

方式二:通过 HTTP 接口手动触发。就是我上面给的HelloController代码,启动后访问http://localhost:8080/api/send,每次访问就发一条消息。

方式三:在 RabbitMQ 网页管理台手动发消息。打开http://localhost:15672,进入 Queues 页面,点击名为hello的队列,往下翻到Publish message区块。在 Routing key 里填hello,Payload 栏里填想发送的文本,然后点击Publish message按钮。消息会通过默认交换器投递到hello队列,Spring Boot 控制台立刻就能收到。

这也是很多人说的 RabbitMQ 网页练习玩法:不需要写任何代码,直接用管理台就能往指定队列灌消息,非常适合用来测试消费者是否正常工作。

4.4 在管理台观察消息流转

管理台不仅是发消息的工具,更是观察消息流转的利器。当你打开Queues页面并点进hello队列,会看到三个关键数字:

  • Ready:队列中等待被消费的消息数
  • Unacked:已经被消费者取走但还没确认的消息数
  • Total:队列历史上总共接收过的消息数

你发一条消息后,可以看到Ready从 0 变 1,随后消费者立刻取走,Ready回到 0,Unacked可能短暂闪到 1 再归零,Total增加 1。整个过程肉眼可见,消息队列的“生产-投递-消费”闭环一下子就通透了。

如果你同时开了多个消费者实例,还会发现一条消息只会被其中一个实例拿到,不会重复投递给多个人,这正是队列典型的工作模式:点对点、互斥消费。

5. 常见问题与排查技巧实录

5.1 Spring Boot 3.x 版本太高?这套代码不受影响

网上很多教程写的时候还是 Spring Boot 2.x 时代,导致新人在 Spring Boot 3.x 下照着抄会踩各种奇怪的坑。我实测下来,本文这套代码在 Spring Boot 3.2.x + JDK 17 + RabbitMQ 3.13 下完全正常。

真要说 3.x 需要注意的地方,其实在 Spring Boot 本身,不在 RabbitMQ 部分:

  • Spring Boot 3.x 最低要求 JDK 17,如果你本机只有 JDK 8,Maven 编译直接报错。
  • 老教程里如果手动引入了旧版amqp-client或旧版spring-rabbit,在 3.x 下会类冲突。解决办法很简单:不要手动指定这些依赖的版本,全部交给 Spring Boot 统一管理。
  • 老代码里如果出现javax.annotation.Resource、javax.xml.bind这类包,那是 JDK 版本变动导致的,和 RabbitMQ 无关,需要改成jakarta包或升级依赖。

总之,遇到“SpringBoot 版本太高导致集成失败”的说法,先检查以上几点,大概率不是 RabbitMQ 本身的问题。

5.2 RabbitMQ 启动失败与 Erlang 版本不匹配

RabbitMQ 启动失败,十次里有八次和 Erlang 版本有关。典型的报错包括Failed to start child、epmd error、version mismatch等。

Windows 上尤其烦人:服务装上了,但启动瞬间又停掉,事件管理器里也看不出个所以然。我的排查步骤是:

  • 去 RabbitMQ 日志目录(一般在C:\Users\你的用户名\AppData\Roaming\RabbitMQ\log\)看启动日志,错误原因会写得非常明确。
  • 确认 Erlang 版本在对应表格范围内,如果不对,卸载重装。
  • 用rabbitmqctl status或者lsof -i:5672看端口是否被占用。如果 5672 被别的进程占了,改端口或者结束占用进程。

Erlang 安装目录如果带有中文或空格,也可能导致服务启动异常,建议把 Erlang 装到默认路径或纯英文路径下。

5.3 Connection refused 与 guest 账号限制

应用能启动,但一发送消息就报Connection refused: localhost/127.0.0.1:5672,这种情况要按顺序排查:

  • 先确认 RabbitMQ 服务真的在运行。很多新手启动 SpringBoot 应用后忘了启动 RabbitMQ,自然连不上。
  • 再确认连接端口是 5672,不是 15672。管理台端口和 AMQP 端口完全不同,端口写错也是高频失误。
  • Windows 防火墙或内网安全策略可能会拦掉 5672,本地调试一般没事,远程连就得放行端口。

还有个常见坑是 guest 账号。RabbitMQ 默认的 guest 用户只允许从 localhost 访问,如果你在云服务器或虚拟机上,用 guest 从外部连接会被拒绝。解决办法一是本地调试就用 localhost,二是用rabbitmqctl add_user和rabbitmqctl set_permissions新建一个远程用户并授予权限。

5.4 消息发了但收不到:队列声明坑点实录

消息发送成功、管理台也能看到队列里有消息,但消费者就是没反应,这属于另一类高频问题。

最常见原因就是前面说的没加@EnableRabbit,或者消费者类没被 Spring 扫描到。另一个容易忽略的是队列名不匹配:生产者发的队列叫hello,消费者监听的队列叫hello2,两边各玩各的,自然收不到。

还有一类坑和队列声明冲突有关。如果你先声明了非持久化队列hello,后来改成持久化声明,再启动应用时会报 406 的PRECONDITION_FAILED错误。原因是队列已经以之前的属性存在于 Broker 中,重复声明但属性不一致时,RabbitMQ 会拒绝。解决办法两种:到管理台把旧队列删掉,或者换一个新队列名。

另外,如果你的消费者方法里处理消息时抛了异常,自动确认模式会把消息重新放回队列,于是你会看见一条消息被反复消费、反复报错的过程。这本身是设计上的保护机制,但新手容易误以为是“消息重复收到”的 bug。Hello World 阶段不需要处理这个,知道有这个行为就行。

我在实际测试中还发现,如果消费者类使用了queuesToDeclare但队列名和生产者 Queue Bean 不一致,Spring 会按注解声明一个新队列,两边对不上,同样收不到。所以最简单的做法就是:全项目统一用同一个队列名,别变来变去。

最后再分享一个小技巧:遇到消息收发问题的时候,先打开管理台看一眼hello队列里的 Ready 数量。如果它一直是 0,说明消息压根没进队列,问题在生产端;如果它一直在涨但消费者没反应,问题在消费端。这一眼就能帮你定位到一半以上的问题。

说实话,RabbitMQ 的 Hello World 看起来是个“小项目”,但真正把它彻底跑通,你手里的底牌就完全不一样了:版本匹配的敏感度有了,Spring Boot 自动配置的路数熟悉了,管理台这个可视化利器也会用了。个人建议,第一遍玩的时候,能不用 Docker 就不用 Docker,先在本机装一个真实服务跑一遍。宁可多报几个错、多翻几次日志,这个过程带来的理解深度,比看十篇教程都管用。后面再去碰交换机绑定、消息确认、死信队列这些进阶内容,你会发现它们都是在今天这套骨架上填肉而已。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询