Spring Boot系列——7步集成RabbitMQ
RabbitMQ是一种我们经常使用的消息中间件,通过RabbitMQ可以帮助我们实现异步、削峰的目的。
今天这篇,我们来看看Spring Boot是如何集成RabbitMQ,发送消息和消费消息的。同时我们介绍下死信队列。
集成RabbitMQ
集成RabbitMQ只需要如下几步即可
1、添加maven依赖
<!--rabbitmq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、添加配置文件application.yaml
在application.yaml添加配置内容如下
spring: rabbitmq:
host: 192.168.1.161
port: 5672
username: guest
password: guest
cache:
channel: size: 10
listener:
type: simple
simple:
acknowledge-mode: auto
concurrency: 5
default-requeue-rejected: true
max-concurrency: 100
retry:
enabled: true # initial-interval: 1000ms
max-attempts: 3 # max-interval: 1000ms
multiplier: 1
stateless: true # publisher-confirms: true</pre>
注意:
这里最基本的配置只需要配置host,port,username和password四个属性即可
其他属性都有各自的含义,比如retry是用于配置重试策略的,acknowledge-mode是配置消息接收确认机制的。
3、编写配置类
编写RabbitConfig配置类,采用Java Configuration的方式配置RabbitTemplate、Exchange和Queue等信息,具体如下所示
package com.jackie.springbootdemo.config;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.util.HashMap;
import java.util.Map;
@Configuration public class RabbitMQConfig implements InitializingBean { @Autowired
SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory;
@Override
public void afterPropertiesSet() throws Exception {
simpleRabbitListenerContainerFactory.setMessageConverter(new Jackson2JsonMessageConverter());
} @Bean("jackson2JsonMessageConverter")
public Jackson2JsonMessageConverter jackson2JsonMessageConverter(ConnectionFactory connectionFactory) {
return new Jackson2JsonMessageConverter();
} @Bean("rabbitTemplate")
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory,
@Qualifier("jackson2JsonMessageConverter") Jackson2JsonMessageConverter jackson2JsonMessageConverter) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(new Jackson2JsonMessageConverter());
return template;
} // --------------------- 声明队列 ------------------------
@Bean
public Queue demoQueue() {
return new Queue("demo_queue");
} // --------------------- 声明exchange ------------------------ @Bean
public DirectExchange demoExchange() {
return new DirectExchange("demo_exchange");
} // --------------------- 队列绑定 ------------------------
@Bean
public Binding bindingAlbumItemCreatedQueue(DirectExchange demoExchange,
Queue demoQueue) {
return BindingBuilder.bind(demoQueue).to(demoExchange).with("100");
} }
注意
这里声明了Direct模式的Exchange,声明一个Queue,并通过routing-key为100将demo_queue绑定到demo_exchange,这样demo_queue就可以接收到demo_exchange发送的消息了。
4、编写消息发送类
package com.jackie.springbootdemo.message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component public class Sender implements RabbitTemplate.ConfirmCallback { private RabbitTemplate rabbitTemplate;
/**
* 构造方法注入 */ @Autowired
public Sender(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果为单例的话,那回调就是最后设置的内容
} public void sendMsg(String content) {
rabbitTemplate.convertAndSend("demo_exchange", "100", content);
} /**
* 回调 */ @Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println(" 回调id:" + correlationData);
if (ack) {
System.out.println("消息成功消费");
} else {
System.out.println("消息消费失败:" + cause);
}
} }
注意
发送内容content,路由到routing-key为100上,则我们就可以在demo_queue队列中看到发送的消息内容了
confirm函数是回调函数,这里因为没有消费者,且acknoledge-mode是auto(其他两种值分别是none和manual),所以ack是false。
5、编写发送消息测试类
package com.jackie.springbootdemo;
import com.jackie.springbootdemo.message.Sender;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootDemoApplication.class) @WebAppConfiguration public class RabbitApplicationTests { @Autowired
Sender sender;
@Test
public void contextLoads() throws Exception {
sender.sendMsg("test");
} }
运行该测试类,我们可以看到如下结果

6、编写消息消费类
package com.jackie.springbootdemo.message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component public class Receiver { @RabbitListener(queues = "demo_queue")
public void created(String message) {
System.out.println("orignal message: " + message);
} }
注意
消息消费类也非常简单,添加注解@RabbitListener,指定要监听的队列名称即可
除了注解@RabbitListener,我们经常还能看到@RabbitHandler,这两个注解可以配合起来使用。
@RabbitListener 标注在类上面表示当有收到消息的时候,就交给 @RabbitHandler 的方法处理,具体使用哪个方法处理,根据 MessageConverter 转换后的参数类型,形如
@RabbitListener(queues = "demo_queue") public class Receiver { @RabbitHandler public void processMessage1(String message) {
System.out.println(message);
} @RabbitHandler
public void processMessage2(byte[] message) {
System.out.println(new String(message));
} }
7、运行消息发送测试类

从执行结果可以看到,因为有了消费者,所以这次打印的结果是"消息消费成功"
而且,我们看到Receiver类将消息消费并打印出消息的内容为"test"。
代码已经提交至项目rome:https://github.com/DMinerJackie/rome
本来准备再说说死信队列的,限于篇幅,后面再写吧。
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

Spring Boot系列——7步集成RabbitMQ的更多相关文章
- Spring Boot实战三:集成RabbitMQ,实现消息确认
Spring Boot集成RabbitMQ相比于Spring集成RabbitMQ简单很多,有兴趣了解Spring集成RabbitMQ的同学可以看我之前的<RabbitMQ学习笔记>系列的博 ...
- Spring Boot系列 八、集成Kafka
一.引入依赖 <dependency> <groupId>org.springframework.kafka</groupId> <artifactId> ...
- Spring Boot系列——死信队列
在说死信队列之前,我们先介绍下为什么需要用死信队列. 如果想直接了解死信对接,直接跳入下文的"死信队列"部分即可. ack机制和requeue-rejected属性 我们还是基于上 ...
- Spring Boot系列——如何集成Log4j2
上篇<Spring Boot系列--日志配置>介绍了Spring Boot如何进行日志配置,日志系统用的是Spring Boot默认的LogBack. 事实上,除了使用默认的LogBack ...
- Spring Boot 系列总目录
一.Spring Boot 系列诞生原因 上学那会主要学的是 Java 和 .Net 两种语言,当时对于语言分类这事儿没什么概念,恰好在2009年毕业那会阴差阳错的先找到了 .Net 的工作,此后就开 ...
- Spring Boot 系列总结
Spring Boot 系列总结 1.SpringBoot自动装配 1.1 Spring装配方式 1.2 Spring @Enable 模块驱动 1.3 Spring 条件装配 2.自动装配正文 2. ...
- Spring Boot 系列教程10-freemarker导出word下载
freemarker FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个 ...
- Spring Boot 系列教程9-swagger-前后端分离后的标准
前后端分离的必要 现在的趋势发展,需要把前后端开发和部署做到真正的分离 做前端的谁也不想用Maven或者Gradle作为构建工具 做后端的谁也不想要用Grunt或者Gulp作为构建工具 前后端需要通过 ...
- 国内最全的Spring Boot系列之二
历史文章 <国内最全的Spring Boot系列之一> 视频&交流平台 SpringBoot视频:http://t.cn/R3QepWG Spring Cloud视频:http:/ ...
随机推荐
- Java使用序列化的私有方法巧妙解决部分属性持久化问题
部分属性持久化问题看似很简单,只要把不需要的持久化的属性加上瞬态关键字(transient关键字)即可,没错,这也是一种解决方案,但在有的时候行不通,例如在一个计税系统和人力系统对接的时候,计税系统需 ...
- PAT (Advanced Level) Practise 1001 解题报告
GiHub markdown PDF 问题描述 解题思路 代码 提交记录 问题描述 A+B Format (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判 ...
- [Python] Marshmallow QuickStart
常用小操作索引 指定fields必须:fields.String(required=True) 部分loading: 不load name:result = UserSchema.load({'ema ...
- Yahoo Programming Contest 2019.E.Odd Subrectangles(思路 线性基)
题目链接 \(Description\) 给定一个\(n\times m\)的\(01\)矩阵.求任意选出\(r\)行.\(c\)列(共\(2^{n+m}\)种方案),使得这\(r\)行\(c\)列的 ...
- 英语口语练习系列-C13-聚会
词汇 音频 1. apartment [əˈpɑ:tmənt] n. 公寓 a big / small apartment 一个大的/小的公寓 in an apartment 在公寓 2. arm [ ...
- Java -- 内部类(一)
什么是内部类 将一个类的定义放在另一个类的定义内部,这就是内部类.在Java中内部类主要分为成员内部类.局部内部类.匿名内部类.静态内部类.举个栗子: public class A { public ...
- 2017-2018-2 20172310『Java程序设计』课程 结对编程练习_四则运算_第二周
2017-2018-2 20172310『Java程序设计』课程 结对编程练习_四则运算_第二周 博客要求 组内同学需各自发表博客 博客中需包含以下内容: 相关过程截图 关键代码解释 遇到的困难及解决 ...
- 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第4章编程练习3
#include <iostream>#include <cstring>using namespace std;int main(){ char fname[20]; cha ...
- redis:hash哈希类型的操作
1. hash哈希类型的操作 1.1. hset key field value 语法:hset key field value 作用:把key中field域的值设为value 注:如果没有field ...
- django中数据库操作有关部分
# >>>>>>>>>>>>>>>>>>>>>>>>&g ...