源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all

一、 项目结构说明

1.1 这里采用maven多模块的构建方式,在spring-boot-rabbitmq下构建三个子模块:

  1. rabbitmq-common 是公共模块,用于存放公共的接口、配置和bean,被rabbitmq-producer和rabbitmq-consumer在pom.xml中引用;
  2. rabbitmq-producer 是消息的生产者模块;
  3. rabbitmq-consumer是消息的消费者模块。

1.2 关于rabbitmq安装、交换机、队列、死信队列等基本概念可以参考我的手记《RabbitMQ实战指南》读书笔记,里面有详细的配图说明。

二、关键依赖

在父工程的项目中统一导入依赖rabbitmq的starter(spring-boot-starter-amqp),父工程的pom.xml如下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <packaging>pom</packaging>
  6. <modules>
  7. <module>rabbitmq-consumer</module>
  8. <module>rabbitmq-producer</module>
  9. <module>rabbitmq-common</module>
  10. </modules>
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>2.1.1.RELEASE</version>
  15. <relativePath/> <!-- lookup parent from repository -->
  16. </parent>
  17. <groupId>com.heibaiying</groupId>
  18. <artifactId>spring-boot-rabbitmq</artifactId>
  19. <version>0.0.1-SNAPSHOT</version>
  20. <name>spring-boot-rabbitmq</name>
  21. <description>RabbitMQ project for Spring Boot</description>
  22. <properties>
  23. <java.version>1.8</java.version>
  24. </properties>
  25. <dependencies>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-amqp</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-web</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-test</artifactId>
  42. <scope>test</scope>
  43. </dependency>
  44. </dependencies>
  45. </project>

三、公共模块(rabbitmq-common)

  • bean 下为公共的实体类。
  • constant 下为公共配置,用静态常量引用。(这里我使用静态常量是为了方便引用,实际中也可以按照情况,抽取为公共配置文件)
  1. package com.heibaiying.constant;
  2. /**
  3. * @author : heibaiying
  4. * @description : rabbit 公用配置信息
  5. */
  6. public class RabbitInfo {
  7. // queue 配置
  8. public static final String QUEUE_NAME = "spring.boot.simple.queue";
  9. public static final String QUEUE_DURABLE = "true";
  10. // exchange 配置
  11. public static final String EXCHANGE_NAME = "spring.boot.simple.exchange";
  12. public static final String EXCHANGE_TYPE = "topic";
  13. // routing key
  14. public static final String ROUTING_KEY = "springboot.simple.*";
  15. }

四、服务消费者(rabbitmq-consumer)

4.1 消息消费者配置

  1. spring:
  2. rabbitmq:
  3. addresses: 127.0.0.1:5672
  4. # RabbitMQ 默认的用户名和密码都是guest 而虚拟主机名称是 "/"
  5. # 如果配置其他虚拟主机地址,需要预先用管控台或者图形界面创建 图形界面地址 http://主机地址:15672
  6. username: guest
  7. password: guest
  8. virtual-host: /
  9. listener:
  10. simple:
  11. # 为了保证信息能够被正确消费,建议签收模式设置为手工签收,并在代码中实现手工签收
  12. acknowledge-mode: manual
  13. # 侦听器调用者线程的最小数量
  14. concurrency: 10
  15. # 侦听器调用者线程的最大数量
  16. max-concurrency: 50

4.2 使用注解@RabbitListener和@RabbitHandler创建消息监听者

  1. 使用注解创建的交换机、队列、和绑定关系会在项目初始化的时候自动创建,但是不会重复创建;
  2. 这里我们创建两个消息监听器,分别演示消息是基本类型和消息是对象时的配置区别。
  1. /**
  2. * @author : heibaiying
  3. * @description : 消息是对象的消费者
  4. */
  5. @Component
  6. @Slf4j
  7. public class RabbitmqBeanConsumer {
  8. @RabbitListener(bindings = @QueueBinding(
  9. value = @Queue(value = RabbitBeanInfo.QUEUE_NAME, durable = RabbitBeanInfo.QUEUE_DURABLE),
  10. exchange = @Exchange(value = RabbitBeanInfo.EXCHANGE_NAME, type = RabbitBeanInfo.EXCHANGE_TYPE),
  11. key = RabbitBeanInfo.ROUTING_KEY)
  12. )
  13. @RabbitHandler
  14. public void onMessage(@Payload Programmer programmer, @Headers Map<String, Object> headers, Channel channel) throws Exception {
  15. log.info("programmer:{} ", programmer);
  16. Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
  17. channel.basicAck(deliveryTag, false);
  18. }
  19. }
  1. @Component
  2. @Slf4j
  3. public class RabbitmqConsumer {
  4. @RabbitListener(bindings = @QueueBinding(
  5. value = @Queue(value = RabbitInfo.QUEUE_NAME, durable = RabbitInfo.QUEUE_DURABLE),
  6. exchange = @Exchange(value = RabbitInfo.EXCHANGE_NAME, type = RabbitInfo.EXCHANGE_TYPE),
  7. key = RabbitInfo.ROUTING_KEY)
  8. )
  9. @RabbitHandler
  10. public void onMessage(Message message, Channel channel) throws Exception {
  11. MessageHeaders headers = message.getHeaders();
  12. // 获取消息头信息和消息体
  13. log.info("msgInfo:{} ; payload:{} ", headers.get("msgInfo"), message.getPayload());
  14. // DELIVERY_TAG 代表 RabbitMQ 向该Channel投递的这条消息的唯一标识ID,是一个单调递增的正整数
  15. Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
  16. // 第二个参数代表是否一次签收多条,当该参数为 true 时,则可以一次性确认 DELIVERY_TAG 小于等于传入值的所有消息
  17. channel.basicAck(deliveryTag, false);
  18. }
  19. }

五、 消息生产者(rabbitmq-producer)

5.1 消息生产者配置

  1. spring:
  2. rabbitmq:
  3. addresses: 127.0.0.1:5672
  4. # RabbitMQ 默认的用户名和密码都是guest 而虚拟主机名称是 "/"
  5. # 如果配置其他虚拟主机地址,需要预先用管控台或者图形界面创建 图形界面地址 http://主机地址:15672
  6. username: guest
  7. password: guest
  8. virtual-host: /
  9. # 是否启用发布者确认 具体确认回调实现见代码
  10. publisher-confirms: true
  11. # 是否启用发布者返回 具体返回回调实现见代码
  12. publisher-returns: true
  13. # 是否启用强制消息 保证消息的有效监听
  14. template.mandatory: true
  15. server:
  16. port: 8090

5.2 创建消息生产者

  1. /**
  2. * @author : heibaiying
  3. * @description : 消息生产者
  4. */
  5. @Component
  6. @Slf4j
  7. public class RabbitmqProducer {
  8. @Autowired
  9. private RabbitTemplate rabbitTemplate;
  10. public void sendSimpleMessage(Map<String, Object> headers, Object message,
  11. String messageId, String exchangeName, String key) {
  12. // 自定义消息头
  13. MessageHeaders messageHeaders = new MessageHeaders(headers);
  14. // 创建消息
  15. Message<Object> msg = MessageBuilder.createMessage(message, messageHeaders);
  16. /* 确认的回调 确认消息是否到达 Broker 服务器 其实就是是否到达交换器
  17. 如果发送时候指定的交换器不存在 ack就是false 代表消息不可达 */
  18. rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
  19. log.info("correlationData:{} , ack:{}", correlationData.getId(), ack);
  20. if (!ack) {
  21. System.out.println("进行对应的消息补偿机制");
  22. }
  23. });
  24. /* 消息失败的回调
  25. * 例如消息已经到达交换器上,但路由键匹配任何绑定到该交换器的队列,会触发这个回调,此时 replyText: NO_ROUTE
  26. */
  27. rabbitTemplate.setReturnCallback((message1, replyCode, replyText, exchange, routingKey) -> {
  28. log.info("message:{}; replyCode: {}; replyText: {} ; exchange:{} ; routingKey:{}",
  29. message1, replyCode, replyText, exchange, routingKey);
  30. });
  31. // 在实际中ID 应该是全局唯一 能够唯一标识消息 消息不可达的时候触发ConfirmCallback回调方法时可以获取该值,进行对应的错误处理
  32. CorrelationData correlationData = new CorrelationData(messageId);
  33. rabbitTemplate.convertAndSend(exchangeName, key, msg, correlationData);
  34. }
  35. }

5.3 以单元测试的方式发送消息

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class RabbitmqProducerTests {
  4. @Autowired
  5. private RabbitmqProducer producer;
  6. /***
  7. * 发送消息体为简单数据类型的消息
  8. */
  9. @Test
  10. public void send() {
  11. Map<String, Object> heads = new HashMap<>();
  12. heads.put("msgInfo", "自定义消息头信息");
  13. // 模拟生成消息ID,在实际中应该是全局唯一的 消息不可达时候可以在setConfirmCallback回调中取得,可以进行对应的重发或错误处理
  14. String id = String.valueOf(Math.round(Math.random() * 10000));
  15. producer.sendSimpleMessage(heads, "hello Spring", id, RabbitInfo.EXCHANGE_NAME, "springboot.simple.abc");
  16. }
  17. /***
  18. * 发送消息体为bean的消息
  19. */
  20. @Test
  21. public void sendBean() {
  22. String id = String.valueOf(Math.round(Math.random() * 10000));
  23. Programmer programmer = new Programmer("xiaoMing", 12, 12123.45f, new Date());
  24. producer.sendSimpleMessage(null, programmer, id, RabbitBeanInfo.EXCHANGE_NAME, RabbitBeanInfo.ROUTING_KEY);
  25. }
  26. }

六、项目构建的说明

因为在项目中,consumer和producer模块均依赖公共模块,所以在构建consumer和producer项目前需要将common 模块安装到本地仓库,依次父工程common模块执行:

  1. mvn install -Dmaven.test.skip = true

consumer中 pom.xml如下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>com.heibaiying</groupId>
  7. <artifactId>spring-boot-rabbitmq</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <artifactId>rabbitmq-consumer</artifactId>
  11. <version>0.0.1-SNAPSHOT</version>
  12. <name>rabbitmq-consumer</name>
  13. <description>RabbitMQ consumer project for Spring Boot</description>
  14. <properties>
  15. <java.version>1.8</java.version>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>com.heibaiying</groupId>
  20. <artifactId>rabbitmq-common</artifactId>
  21. <version>0.0.1-SNAPSHOT</version>
  22. <scope>compile</scope>
  23. </dependency>
  24. </dependencies>
  25. <build>
  26. <plugins>
  27. <plugin>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-maven-plugin</artifactId>
  30. </plugin>
  31. </plugins>
  32. </build>
  33. </project>

producer中 pom.xml如下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>com.heibaiying</groupId>
  7. <artifactId>spring-boot-rabbitmq</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <artifactId>rabbitmq-producer</artifactId>
  11. <version>0.0.1-SNAPSHOT</version>
  12. <name>rabbitmq-producer</name>
  13. <description>RabbitMQ producer project for Spring Boot</description>
  14. <properties>
  15. <java.version>1.8</java.version>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>com.heibaiying</groupId>
  20. <artifactId>rabbitmq-common</artifactId>
  21. <version>0.0.1-SNAPSHOT</version>
  22. <scope>compile</scope>
  23. </dependency>
  24. </dependencies>
  25. <build>
  26. <plugins>
  27. <plugin>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-maven-plugin</artifactId>
  30. </plugin>
  31. </plugins>
  32. </build>
  33. </project>

附:源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all

spring boot 2.x 系列 —— spring boot 整合 RabbitMQ的更多相关文章

  1. spring boot实战(第十二篇)整合RabbitMQ

    前言 最近几篇文章将围绕消息中间件RabbitMQ展开,对于RabbitMQ基本概念这里不阐述,主要讲解RabbitMQ的基本用法.Java客户端API介绍.spring Boot与RabbitMQ整 ...

  2. spring boot 2.x 系列 —— spring boot 整合 redis

    文章目录 一.说明 1.1 项目结构 1.2 项目主要依赖 二.整合 Redis 2.1 在application.yml 中配置redis数据源 2.2 封装redis基本操作 2.3 redisT ...

  3. spring boot 2.x 系列 —— spring boot 整合 druid+mybatis

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构 项目查询用的表对应的建表语句放置在resour ...

  4. spring boot 2.x 系列 —— spring boot 整合 servlet 3.0

    文章目录 一.说明 1.1 项目结构说明 1.2 项目依赖 二.采用spring 注册方式整合 servlet 2.1 新建过滤器.监听器和servlet 2.2 注册过滤器.监听器和servlet ...

  5. spring boot 2.x 系列 —— spring boot 整合 kafka

    文章目录 一.kafka的相关概念: 1.主题和分区 2.分区复制 3. 生产者 4. 消费者 5.broker和集群 二.项目说明 1.1 项目结构说明 1.2 主要依赖 二. 整合 kafka 2 ...

  6. spring boot 2.x 系列 —— spring boot 整合 dubbo

    文章目录 一. 项目结构说明 二.关键依赖 三.公共模块(boot-dubbo-common) 四. 服务提供者(boot-dubbo-provider) 4.1 提供方配置 4.2 使用注解@Ser ...

  7. spring boot 2.x 系列 —— spring boot 实现分布式 session

    文章目录 一.项目结构 二.分布式session的配置 2.1 引入依赖 2.2 Redis配置 2.3 启动类上添加@EnableRedisHttpSession 注解开启 spring-sessi ...

  8. 2018年分享的Spring Cloud 2.x系列文章

    还有几个小时2018年就要过去了,盘点一下小编从做做公众号以来发送了273篇文章,其中包含原创文章90篇,虽然原创的有点少,但是2019年小编将一如既往给大家分享跟多的干货,分享工作中的经验,让大家在 ...

  9. spring boot&&cloud干货系列

    接触spring boot也有些时日了,刚开始博主还想参照官方参考指南自己写一个系列的入门式的教程,包含spring boot的所有模块的用法,后来发现,有一大波优秀的系列文章和项目了,所以就没班门弄 ...

随机推荐

  1. delphi 颜色,字体保存到INI文件

    颜色转换成整型保存{也可以用ColorToString  / stringTOColor}字体用下面的函数转换成字符串,然后保存 unit xFonts; interface uses Classes ...

  2. 利用反汇编手段解析C语言函数

    1.问题的提出函数是 C语言中的重要概念.利用好函数能够充分利用系统库的功能写出模块独立.易于维护和修改的程序.函数并不是 C 语言独有的概念,其他语言中的方法.过程等本质上都是函数.可见函数在教学中 ...

  3. Windows10的Ubuntu子系统开启桌面环境

    原文:Windows10的Ubuntu子系统开启桌面环境 Ubuntu 优势之一就是桌面环境比较好,所以咱们的子系统当然也不能少了这一环节,本小结开始安装Ubuntu 桌面系统. 安装环境 使用下面指 ...

  4. Matlab Tricks(二十六)—— 置乱(随机化)与恢复(shuffle/permutation & restore)

    x = 1:10; n = length(x); perm = randperm(n); x_perm = x(perm); % x_perm 表示置乱后的结果 x_ori(perm) = x_per ...

  5. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[BandedSwirl]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[BandedSwirl] 因工作原因,需要在Silverlight中使用Pixel Shader技术,这对于我来 ...

  6. HTML5 随手记(4)

    新中国 chrome 不支持 -webkit-text-size-adjust 设定.可以小于 12px.为了尺寸小于 12px 和清晰的显示效果,现在无解(scale 不清楚) 版权声明:本文博客原 ...

  7. Matlab随笔之求解线性方程

    原文:Matlab随笔之求解线性方程 理论知识补充: %矩阵除分为矩阵右除和矩阵左除. %矩阵右除的运算符号为“/”,设A,B为两个矩阵,则“A/B”是指方程X*B=A的解矩阵X. %矩阵A和B的列数 ...

  8. Qt5.8 下链接 Mysql 错误以及解决方法(无论 Mysql 是什么版本的,64 位 Qt 要用 64 位的 Mysql 驱动,32 位的 Qt 要用 32 位的Mysql 驱动)

    Qt 5.8 下链接 Mysql(Windows 平台下),有朋友会出现一个这个无法连接的错误 QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: ...

  9. Go 语言如果按这样改进,能不能火过 Java?

    据 InfoWorld 消息,为改进 Go 语言的开发工具,Go 可能会获得自己的语言服务器,类似于 Microsoft 和 Red Hat 的语言服务器协议. 消息是从 Go 语言开发者的讨论组中流 ...

  10. fileapi.h里的API函数(包括LockFileEx和FindFirstChangeNotification函数)

    /** * This file is part of the mingw-w64 runtime package. * No warranty is given; refer to the file ...