先决条件

  1. rabbitmq server 安装参考
  2. 一个添加了 web 依赖的 spring boot 项目 我的版本是 2.5.2

添加 maven 依赖

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

配置 application.yml

spring:
rabbitmq:
host: [此处填写 rabbitmq 服务地址(ip/domain),不包括[]]
port: [此处填写 rabbitmq 服务端口(默认是 5672),不包括[]]
username: [此处填写用户名,不包括[]]
password: [此处填写密码,不包括[]]

添加 config bean

这里面只需要配置 MessageConverter,其他的可以不用配置,它的作用是:

  1. 发布消息时,将 java bean 序列化为 rabbitmq 的消息
  2. 消费消息时,将 rabbitmq 消息反序列化为 java bean

如果你只用简单类型发布和接收消息,就大可不必配置这个了

package com.xx.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 { /**
* MessageConverter用于将Java对象转换为RabbitMQ的消息。
*
* 默认情况下,Spring Boot使用SimpleMessageConverter,只能发送String和byte[]类型的消息,不太方便。
* 使用Jackson2JsonMessageConverter,我们就可以发送JavaBean对象,由Spring Boot自动序列化为JSON并以文本消息传递。
*
*
* convertAndSend 可以发送 java bean,接收方也可也自动反序列化
* https://www.liaoxuefeng.com/wiki/1252599548343744/1282385960239138
* http://www.ityouknow.com/springboot/2016/11/30/spring-boot-rabbitMQ.html
*
* @return
*/
@Bean
MessageConverter createMessageConverter() {
return new Jackson2JsonMessageConverter();
}

配置队列

  1. 配置 exchange
  2. 配置 queue
  3. 配置 binding

配置好之后,会自动创建 exchangequeuebinding,不需要手动在 rabbitmq web management ui 中手动操作了。

这块配置代码如下:

Constant 类根据自己情况,要不要看你自己

package com.xx.constant;

public final class Constant {

    /**
* rabbitmq
*/
public static final class MQ { /**
* XX 消息采用 Direct Exchange 模式
*/
public static final class XX { private static final String namePrefix = "company-module-";
private static final String routingKeyPrefix = "company_module_";
private static final String create = "create";
private static final String update = "update"; public static final String exchange = namePrefix + "events"; public static final class Queue {
public static final String create = namePrefix + XX.create;
public static final String update = namePrefix + XX.update;
} public static final class RoutingKey {
public static final String create = routingKeyPrefix + XX.create;
public static final String update = routingKeyPrefix + XX.update;
}
}
}
}
package com.xx.message.receiver.xx;

import com.xx.constant.Constant;
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; @Configuration
public class RabbitMQXXConfig { @Bean
public DirectExchange xxExchange() {
return new DirectExchange(Constant.MQ.XX.exchange, true, false);
} @Bean
public Queue xxCreateQueue() {
return new Queue(Constant.MQ.XX.Queue.create, true, false, false);
} @Bean
public Queue xxUpdateQueue() {
return new Queue(Constant.MQ.XX.Queue.update, true, false, false);
} @Bean
public Binding xxCreateBinding() {
return BindingBuilder
.bind(xxCreateQueue())
.to(xxExchange())
.with(Constant.MQ.XX.RoutingKey.create);
} @Bean
public Binding xxUpdateBinding() {
return BindingBuilder
.bind(xxUpdateQueue())
.to(xxExchange())
.with(Constant.MQ.XX.RoutingKey.update);
}
}

编写 messageReceiver

这里为了测试,把 createupdate 的消息接收器写了两个,实际一个就可以了

package com.xx.message.receiver.xx;

import com.xx.constant.Constant;
import com.xx.exception.ServiceException;
import com.xx.vo.xx.XXVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component; /**
* XX 消息接收器
*/
@Slf4j
@Component
public class RabbitMQXXMessageReceiver { @RabbitListener(queues = Constant.MQ.XX.Queue.create)
public void onCreate1Message(XXVo message) {
log.info("mq:xx-create1 received <{}>", message); // throw new ServiceException("报错模拟");
} @RabbitListener(queues = Constant.MQ.XX.Queue.create)
public void onCreate2Message(XXVo message) {
log.info("mq:xx-create2 received <{}>", message); // throw new ServiceException("报错模拟");
} @RabbitListener(queues = Constant.MQ.XX.Queue.update)
public void onUpdate1Message(XXVo message) {
log.info("mq:xx-update1 received <{}>", message);
} @RabbitListener(queues = Constant.MQ.XX.Queue.update)
public void onUpdate2Message(XXVo message) {
log.info("mq:xx-update2 received <{}>", message);
}
}

发布消息

你可以用自己喜欢的方式发送,我这里用 RestController

package com.xx.controller;

import com.xx.constant.Constant;
import com.xx.vo.xx.XXVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; @Slf4j
@RestController()
@RequestMapping("mq")
public class MQController { private final RabbitTemplate rabbitTemplate; public MQController(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
} @GetMapping("create")
public ResponseEntity<String> create(){
final XXVo message = new XXVo()
.setName("myesn"); rabbitTemplate.convertAndSend(
Constant.MQ.XX.exchange,
Constant.MQ.XX.RoutingKey.create,
message);
// log.info("pub: send create message"); return ResponseEntity.ok("create pub");
} @GetMapping("update")
public ResponseEntity<String> update(){
final XXVo message = new XXVo()
.setName("myesn"); rabbitTemplate.convertAndSend(
Constant.MQ.XX.exchange,
Constant.MQ.XX.RoutingKey.update,
message);
// log.info("pub: send update message"); return ResponseEntity.ok("update pub");
}

测试

现在可以通过 http://ip:port/mq/createhttp://ip:port/mq/update 来测试消息的发布与消费

总结

示例中只使用了 direct exchange 模式,并且最终是 point to point 的通道类型(channel)。

在消息系统标准协议中,一个队列只能被一个消费者消费,如果想一个消息被多个消费者同时消费(发布消息后,所有消费者都能收到),那么就需要多个 queue 了。

测试总结(归纳文章要点):

  1. 自动创建 exchange、queue、binding,不需要手动在 web 上创建
  2. exchange、queue 持久化,rabbitmq 重启或无客户端时都不会自动删除 exchange、queue
  3. 消费者消费过程中报错,消息不会丢失,会自动切换到其他监听此队列的消费者(如果没有消息就一直被持久化),如果网站做了负载均衡,它也会自动让其他实例消费,如果负载均衡中所有节点中的消费者都报错,它也会一直循环在各个节点中消费消息,消息不会丢失,只有消费者成功消费消息(没有任何抛错),它才会从队列中移除此消息,点赞

文章参考

  1. RabbitMQ中的Exchange Types
  2. RabbitMQ Exchange类型详解
  3. RabbitMQ各个参数含义

我自己也整理了一份 xmind 放在 github,但 repo 目前是 private 的,就不开放了。

spring boot 集成 rabbitmq 指南的更多相关文章

  1. Spring Boot 集成 RabbitMQ 实战

    Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...

  2. Spring boot集成RabbitMQ(山东数漫江湖)

    RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出 ...

  3. 85. Spring Boot集成RabbitMQ【从零开始学Spring Boot】

    这一节我们介绍下Spring Boot整合RabbitMQ,对于RabbitMQ这里不过多的介绍,大家可以参考网络上的资源进行安装配置,本节重点是告诉大家如何在Spring Boot中使用Rabbit ...

  4. RabbitMQ(3) Spring boot集成RabbitMQ

    springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持. 资源代码:练习用的代码. ...

  5. spring boot集成RabbitMQ

    原文:https://www.jianshu.com/p/e1258c004314 RabbitMQ作为AMQP的代表性产品,在项目中大量使用.结合现在主流的spring boot,极大简化了开发过程 ...

  6. Spring Boot 集成RabbitMQ

    在Spring Boot中整合RabbitMQ是非常容易的,通过在Spring Boot应用中整合RabbitMQ,实现一个简单的发送.接收消息的例子. 首先需要启动RabbitMQ服务,并且add一 ...

  7. spring boot 集成 rabbitmq

    1.使用默认的AmqpTemplate生产消费pojo时,pojo需要implement Serializable,否则会抛出org.springframework.amqp.AmqpExceptio ...

  8. spring boot 集成RabbitMQ的异常

    com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.clos ...

  9. Spring boot集成Rabbit MQ使用初体验

    Spring boot集成Rabbit MQ使用初体验 1.rabbit mq基本特性 首先介绍一下rabbitMQ的几个特性 Asynchronous Messaging Supports mult ...

随机推荐

  1. 全网最硬核 Java 新内存模型解析与实验单篇版(不断更新QA中)

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  2. Python - random库介绍

  3. 体温填报app作业演示

    今日学习 今天把这个体温填写app作业,做完了. 具体开发流程:https://www.cnblogs.com/yuxuan-light-of-Taihu-Lake/p/14362107.html 点 ...

  4. 微信小程序常用表单校验方法(手机号校验、身份证号(严格和非严格校验、验证码六位数字校验))

    util.js function isPhone(value) { if (!/^1(3|4|5|7|8)\d{9}$/.test(value)) { return false } else { re ...

  5. 使用Socket实现HttpServer(一)

    使用Socket实现HttpServer(一) Socket 编程 socket 翻译过来叫插槽,一张图你就明白 socket 就插在 TCP 也就是传输层上,对用户的请求和服务器的响应进行处理. 下 ...

  6. Arrays工具类与Collections工具类

    Arrays工具类 : Arrays.sort():对指定数组进行排序,从小到大 Arrays.toString():返回数组的内容的字符串表示形式 Arrays.asList():数组转List,但 ...

  7. Spring的事务控制-基于xml方式

    介绍:该程序模拟了转账操作,即Jone减少500元,tom增加500元 1.导入坐标 <dependency> <groupId>junit</groupId> & ...

  8. 基于File NIO写的一个文件新增内容监控器

    基于File NIO写的一个文件新增内容监控器 需求说明 监控一个文件,如果文件有新增内容,则在控制台打印出新增内容. 代码示例 FileMoniter文件监控器类 package com.black ...

  9. 帝国cms发布文章对哪些数据表做了操作

    帝国cms 发布一篇文章会影响哪些数据表 insert into phome_enewsfile_1(pubid,filename,filesize,adduser,path,filetime,cla ...

  10. 记一次线上websocket返回400问题排查

    现象 生产环境websocket无法正常连接,服务端返回400 bad request,开发及测试环境均正常. 抓包排查 src:nginx服务器 172.16.177.193dst:imp应用服务器 ...