spring boot 集成 rabbitmq 指南
先决条件
- rabbitmq server 安装参考
- 一个添加了 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,其他的可以不用配置,它的作用是:
- 发布消息时,将 java bean 序列化为 rabbitmq 的消息
- 消费消息时,将 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();
}
配置队列
- 配置 exchange
- 配置 queue
- 配置 binding
配置好之后,会自动创建 exchange、queue、binding,不需要手动在 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
这里为了测试,把 create、update 的消息接收器写了两个,实际一个就可以了
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/create 或 http://ip:port/mq/update 来测试消息的发布与消费
总结
示例中只使用了 direct exchange 模式,并且最终是 point to point 的通道类型(channel)。
在消息系统标准协议中,一个队列只能被一个消费者消费,如果想一个消息被多个消费者同时消费(发布消息后,所有消费者都能收到),那么就需要多个 queue 了。
测试总结(归纳文章要点):
- 自动创建 exchange、queue、binding,不需要手动在 web 上创建
- exchange、queue 持久化,rabbitmq 重启或无客户端时都不会自动删除 exchange、queue
- 消费者消费过程中报错,消息不会丢失,会自动切换到其他监听此队列的消费者(如果没有消息就一直被持久化),如果网站做了负载均衡,它也会自动让其他实例消费,如果负载均衡中所有节点中的消费者都报错,它也会一直循环在各个节点中消费消息,消息不会丢失,只有消费者成功消费消息(没有任何抛错),它才会从队列中移除此消息,点赞
文章参考
我自己也整理了一份 xmind 放在 github,但 repo 目前是 private 的,就不开放了。
spring boot 集成 rabbitmq 指南的更多相关文章
- Spring Boot 集成 RabbitMQ 实战
Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...
- Spring boot集成RabbitMQ(山东数漫江湖)
RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出 ...
- 85. Spring Boot集成RabbitMQ【从零开始学Spring Boot】
这一节我们介绍下Spring Boot整合RabbitMQ,对于RabbitMQ这里不过多的介绍,大家可以参考网络上的资源进行安装配置,本节重点是告诉大家如何在Spring Boot中使用Rabbit ...
- RabbitMQ(3) Spring boot集成RabbitMQ
springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持. 资源代码:练习用的代码. ...
- spring boot集成RabbitMQ
原文:https://www.jianshu.com/p/e1258c004314 RabbitMQ作为AMQP的代表性产品,在项目中大量使用.结合现在主流的spring boot,极大简化了开发过程 ...
- Spring Boot 集成RabbitMQ
在Spring Boot中整合RabbitMQ是非常容易的,通过在Spring Boot应用中整合RabbitMQ,实现一个简单的发送.接收消息的例子. 首先需要启动RabbitMQ服务,并且add一 ...
- spring boot 集成 rabbitmq
1.使用默认的AmqpTemplate生产消费pojo时,pojo需要implement Serializable,否则会抛出org.springframework.amqp.AmqpExceptio ...
- spring boot 集成RabbitMQ的异常
com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.clos ...
- Spring boot集成Rabbit MQ使用初体验
Spring boot集成Rabbit MQ使用初体验 1.rabbit mq基本特性 首先介绍一下rabbitMQ的几个特性 Asynchronous Messaging Supports mult ...
随机推荐
- 『忘了再学』Shell基础 — 6、Bash基本功能(输入输出重定向)
目录 1.Bash的标准输入输出 2.输出重定向 (1)标准输出重定向 (2)标准错误输出重定向 (3)正确输出和错误输出同时保存 3.输入重定向 1.Bash的标准输入输出 我们前边一直在说,在Li ...
- Nuxt.js的踩坑指南(常见问题汇总)
本文会不定期更新在nuxt.js中遇到的问题进行汇总.转发请注明出处,尊重作者,谢谢! 强烈推荐作者文档版踩坑指南,点击跳转踩坑指南 在Nuxt的官方文档中,中文文档和英文文档都存在着不小的差异. 1 ...
- 前端调试利器 - Charles
Docs 开发之 Charles 配置指南 1.下载与安装 charles-proxy-4.1.4 .dmg56.12 MB已存到云盘下载 2.激活 使用公司正版license 激活 安装证书 点击证 ...
- 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
概述 最近,有客户向我们请求开发一个前端下拉控件,需求是显示了一个列表,其中包含可由用户单独选择的项目控件,该控件将在下拉列表中显示多选TreeView(树形图). 如今WijmoJS已经实现了该控件 ...
- 两个echarts地图联动高亮区域
项目要求左右两张地图能够在鼠标悬浮的时候高亮部分联动,曾尝试了connect不好使,所以自己写了这段代码.代码思路为: 鼠标移入地图时,另一侧的地图根据鼠标悬浮获取到的区域name使该区域高亮: 鼠标 ...
- vue重构--H5--canvas实现粒子时钟
上一篇文章讲解了如何用js+canvas实现粒子时钟,本篇文章 ,主要是使用vue重构,让它在vue也能使用. 我们使用简单的方式重构,不使用vue工程,先加入vue cdn的地址,如下: <s ...
- JavaScript 工作原理之六-WebAssembly 对比 JavaScript 及其使用场景
原文请查阅这里,略有改动,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第六章. 现在 ...
- javaweb之连接数据库
最近做完了一个图书系统的增删改查,想着来总结一下这几个月的所学内容. 一.首先你需要在电脑上安装上mysql或者sql server(本文以mysql为例) mysql官网:MySQL :: Begi ...
- 【Android开发】【布局】 仿QQ的UI
Demo地址
- java中如何能把一个字符串转成日期对象
题目3.1: 把一个字符串转成日期对象 当我们想根据输入字符串得到一个日期对象时我们不知道,应该以什么格式写这个字符串,才能被系统正确解析,一种聪明的做法是,马克-to-win,我们先 把日期对象根据 ...