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,usernamepassword四个属性即可

其他属性都有各自的含义,比如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"。

代码已经提交至项目romehttps://github.com/DMinerJackie/rome

本来准备再说说死信队列的,限于篇幅,后面再写吧。

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

Spring Boot系列——7步集成RabbitMQ的更多相关文章

  1. Spring Boot实战三:集成RabbitMQ,实现消息确认

    Spring Boot集成RabbitMQ相比于Spring集成RabbitMQ简单很多,有兴趣了解Spring集成RabbitMQ的同学可以看我之前的<RabbitMQ学习笔记>系列的博 ...

  2. Spring Boot系列 八、集成Kafka

    一.引入依赖 <dependency> <groupId>org.springframework.kafka</groupId> <artifactId> ...

  3. Spring Boot系列——死信队列

    在说死信队列之前,我们先介绍下为什么需要用死信队列. 如果想直接了解死信对接,直接跳入下文的"死信队列"部分即可. ack机制和requeue-rejected属性 我们还是基于上 ...

  4. Spring Boot系列——如何集成Log4j2

    上篇<Spring Boot系列--日志配置>介绍了Spring Boot如何进行日志配置,日志系统用的是Spring Boot默认的LogBack. 事实上,除了使用默认的LogBack ...

  5. Spring Boot 系列总目录

    一.Spring Boot 系列诞生原因 上学那会主要学的是 Java 和 .Net 两种语言,当时对于语言分类这事儿没什么概念,恰好在2009年毕业那会阴差阳错的先找到了 .Net 的工作,此后就开 ...

  6. Spring Boot 系列总结

    Spring Boot 系列总结 1.SpringBoot自动装配 1.1 Spring装配方式 1.2 Spring @Enable 模块驱动 1.3 Spring 条件装配 2.自动装配正文 2. ...

  7. Spring Boot 系列教程10-freemarker导出word下载

    freemarker FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个 ...

  8. Spring Boot 系列教程9-swagger-前后端分离后的标准

    前后端分离的必要 现在的趋势发展,需要把前后端开发和部署做到真正的分离 做前端的谁也不想用Maven或者Gradle作为构建工具 做后端的谁也不想要用Grunt或者Gulp作为构建工具 前后端需要通过 ...

  9. 国内最全的Spring Boot系列之二

    历史文章 <国内最全的Spring Boot系列之一> 视频&交流平台 SpringBoot视频:http://t.cn/R3QepWG Spring Cloud视频:http:/ ...

随机推荐

  1. 大数据小白系列——MR(1)

    一部编程发展史就是一部程序员偷懒史,MapReduce(下称MR)同样是程序员们用来偷懒的工具. 来了一份大数据,我们写了一个程序准备分析它,需要怎么做? 老式的处理方法不行,数据量太大时,所需的时间 ...

  2. C# 自定义等待窗口

    private SynchronizationContext syncContext = null; public WaitWindow() { InitializeComponent(); sync ...

  3. Android图片缓存框架Glide

    Android图片缓存框架Glide Glide是Google提供的一个组件.它具有获取.解码和展示视频剧照.图片.动画等功能.它提供了灵活的API,帮助开发者将Glide应用在几乎任何网络协议栈中. ...

  4. 潭州课堂25班:Ph201805201 django框架 第六课 模型类增删改查,常用 的查询矣查询条件 (课堂笔记)

    在视图函数中写入增删改查的方法 增: 在 urls 中配置路径 : 查: 1: 在后台打印数据 在模型类中添加格式化输出 : QuerySet,反回的是个对象,可以按索引聚会,用 for 循环,, 找 ...

  5. sql server 高级查询

    --in和not in子查询 --采用in子查询获得参加考试的在读学生名单select StudentId,StudentName from Student where StudentId in(se ...

  6. 移动端触屏滑动,JS事件

    先了解下 移动端的触屏滑动 毕竟这玩意其实和PC端还是有一定的区别的 hh 整理了下网上的资料放一放 移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等 ...

  7. 关于ajax请求后js绑定事件失效问题解决方法

    <script> $(function(){ $(document).on('click', '.add' ,function(){ window.location.href=" ...

  8. Scrapy Crawl 运行出错 AttributeError: 'xxxSpider' object has no attribute '_rules' 的问题解决

    按照官方的文档写的demo,只是多了个init函数,最终执行时提示没有_rules这个属性的错误日志如下: ...... File "C:\ProgramData\Anaconda3\lib ...

  9. Python-copy()与deepcopy()区别

    http://blog.csdn.net/qq_32907349/article/details/52190796 学习过程中发现copy()和deepcopy()这对好基友实在是有点过分,搞的博主就 ...

  10. redis:hash哈希类型的操作

    1. hash哈希类型的操作 1.1. hset key field value 语法:hset key field value 作用:把key中field域的值设为value 注:如果没有field ...