先决条件

  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. 学习GlusterFS(三)

    glusterfs,GNU cluster file system,创始人Anand Babu Periasamy,目标:代替开源Lustre和商业产品GPFS,glusterfs是什么: cloud ...

  2. nginx静态资源服务器配置

    编辑 nginx.conf server { listen 80; server_name file.youxiu326.xin; location /image/ { #访问 file.youxiu ...

  3. CEPH-3:cephfs功能详解

    ceph集群cephfs使用详解 一个完整的ceph集群,可以提供块存储.文件系统和对象存储. 本节主要介绍文件系统cephfs功能如何灵活的使用,集群背景: [cephadmin@yq01-aip- ...

  4. 移动端比1px还小的border

    巧用border 在移动端 经常出现border,细边框但有的时候 产品大大1px甚至乎会觉得不够细那么要如何写出比1px还要小的border下面是代码 希望对大家有所帮助 .thinner-bord ...

  5. 前端性能优化(JavaScript篇)

    正巧看到在送书,于是乎找了找自己博客上记录过的一些东西来及其无耻的蹭书了~~~ 小广告:更多内容可以看我的博客 优化循环 如果现在有个一个data[]数组,需要对其进行遍历,应当怎么做?最简单的代码是 ...

  6. 基于canvas和web audio实现低配版MikuTap

    导言 最近发掘了一个特别happy的网页小游戏--MikuTap.打开之后沉迷了一下午,导致开发工作没做完差点就要删库跑路了,还好boss瞥了我一眼就没下文了.于是第二天我就继续沉迷,随着一阵抽搐,这 ...

  7. 小程序拿checkbox的checked属性

     方法一.checkbox <checkbox class="round red" bindtap="checkboxChange" checked=&q ...

  8. 设计模式学习笔记(十四)责任链模式实现以及在Filter中的应用

    责任链模式(Chain Of Responsibility Design Pattern),也叫做职责链,是将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求.当有请求发生时,可将请求沿着这条 ...

  9. C语言-操作符与表达式

    C语言入门之操作符与表达式 前言 本篇文章主要包括各种操作符的介绍与表达式求值,欢迎各位小伙伴与我一起学习. 一.操作符 分类 算术操作符 移位操作符 位操作符 赋值操作符 单目运算符 关系操作符 逻 ...

  10. shell、bash和sh区别

    shell是你(用户)和Linux(或者更准确的说,是你和Linux内核)之间的接口程序.你在提示符下输入的每个命令都由shell先解释然后传给Linux内核. shell 是一个命令语言解释器(co ...