手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(九) - Spring A...
source link: https://www.cnblogs.com/xxyopen/p/16350743.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(九) - Spring AMQP 集成与配置
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(一) - 介绍
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(二) - 数据库设计
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(三) - 项目初始化
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(四) - 日志 & 跨域配置
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(五) - MyBatis-Plus & 代码生成器集成与配置
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(六) - 本地缓存 Caffeine 和 分布式缓存 Redis 集成与配置
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(七) - Elasticsearch 8.2 集成与配置
手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(八) - XXL-JOB 集成与配置
Spring AMQP 介绍
AMQP(高级消息队列协议)是一个异步消息传递所使用的应用层协议规范,为面向消息的中间件设计,不受产品和开发语言的限制. Spring AMQP 将核心 Spring 概念应用于基于 AMQP 消息传递解决方案的开发。
RabbitMQ 是基于 AMQP 协议的轻量级、可靠、可扩展、可移植的消息中间件,Spring 使用 RabbitMQ 通过 AMQP 协议进行通信。Spring Boot 为通过 RabbitMQ 使用 AMQP 提供了多种便利,包括 spring-boot-starter-amqp “Starter”。
Spring AMQP 集成与配置
- 可通过如下 Docker 命令 安装 RabbiMQ:
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.10-management
- 登录 RabbiMQ 的 web 管理界面,创建虚拟主机
novel
:
- 项目中加入如下的 maven 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId></dependency>
- 在 application.yml 配置文件中加入 RabbitMQ 的连接配置:
spring: rabbitmq: addresses: "amqp://guest:[email protected]" virtual-host: novel template: retry: # 开启重试 enabled: true # 最大重试次数 max-attempts: 3 # 第一次和第二次重试之间的持续时间 initial-interval: "3s"
- 此时已经可以在 Spring Beans 中注入 AmqpTemplate 发送消息了。
Spring AMQP 使用示例
- 在
io.github.xxyopen.novel.core.constant
包下创建 AMQP 相关常量类:
/** * AMQP 相关常量 * * @author xiongxiaoyang * @date 2022/5/25 */public class AmqpConsts { /** * 小说信息改变 MQ * */ public static class BookChangeMq{ /** * 小说信息改变交换机 * */ public static final String EXCHANGE_NAME = "EXCHANGE-BOOK-CHANGE"; /** * Elasticsearch book 索引更新的队列 * */ public static final String QUEUE_ES_UPDATE = "QUEUE-ES-BOOK-UPDATE"; /** * Redis book 缓存更新的队列 * */ public static final String QUEUE_REDIS_UPDATE = "QUEUE-REDIS-BOOK-UPDATE"; // ... 其它的更新队列 } }
- 在
io.github.xxyopen.novel.core.config
包下创建 AMQP 配置类,配置各个交换机、队列以及绑定关系:
/** * AMQP 配置类 * * @author xiongxiaoyang * @date 2022/5/25 */@Configurationpublic class AmqpConfig { /** * 小说信息改变交换机 */ @Bean public FanoutExchange bookChangeExchange() { return new FanoutExchange(AmqpConsts.BookChangeMq.EXCHANGE_NAME); } /** * Elasticsearch book 索引更新队列 */ @Bean public Queue esBookUpdateQueue() { return new Queue(AmqpConsts.BookChangeMq.QUEUE_ES_UPDATE); } /** * Elasticsearch book 索引更新队列绑定到小说信息改变交换机 */ @Bean public Binding esBookUpdateQueueBinding() { return BindingBuilder.bind(esBookUpdateQueue()).to(bookChangeExchange()); } // ... 其它的更新队列以及绑定关系 }
- 在
io.github.xxyopen.novel.manager.mq
包下创建 AMQP 消息管理类,用来发送各种 AMQP 消息:
/** * AMQP 消息管理类 * * @author xiongxiaoyang * @date 2022/5/25 */@Component@RequiredArgsConstructorpublic class AmqpMsgManager { private final AmqpTemplate amqpTemplate; @Value("${spring.amqp.enable}") private String enableAmqp; /** * 发送小说信息改变消息 */ public void sendBookChangeMsg(Long bookId) { if (Objects.equals(enableAmqp, CommonConsts.TRUE)) { sendAmqpMessage(amqpTemplate, AmqpConsts.BookChangeMq.EXCHANGE_NAME, null, bookId); } } private void sendAmqpMessage(AmqpTemplate amqpTemplate, String exchange, String routingKey, Object message) { // 如果在事务中则在事务执行完成后再发送,否则可以直接发送 if (TransactionSynchronizationManager.isActualTransactionActive()) { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { amqpTemplate.convertAndSend(exchange, routingKey, message); } }); return; } amqpTemplate.convertAndSend(exchange, routingKey, message); } }
- 在小说信息更新后,发送 AMQP 消息:
@Transactional(rollbackFor = Exception.class)@Overridepublic RestResp<Void> saveBookChapter(ChapterAddReqDto dto) { // 1) 保存章节相关信息到小说章节表 // a) 查询最新章节号 // b) 设置章节相关信息并保存 // 2) 保存章节内容到小说内容表 // 3) 更新小说表最新章节信息和小说总字数信息 // a) 更新小说表关于最新章节的信息 // b) 发送小说信息更新的 MQ 消息 amqpMsgManager.sendBookChangeMsg(dto.getBookId()); return RestResp.ok();}
- 在
io.github.xxyopen.novel.core.listener
包下创建 Rabbit 队列监听器,监听各个 RabbitMQ 队列的消息并处理:
/** * Rabbit 队列监听器 * * @author xiongxiaoyang * @date 2022/5/25 */@Component@RequiredArgsConstructor@Slf4jpublic class RabbitQueueListener { private final BookInfoMapper bookInfoMapper; private final ElasticsearchClient esClient; /** * 监听小说信息改变的 ES 更新队列,更新最新小说信息到 ES * */ @RabbitListener(queues = AmqpConsts.BookChangeMq.QUEUE_ES_UPDATE) @SneakyThrows public void updateEsBook(Long bookId) { BookInfo bookInfo = bookInfoMapper.selectById(bookId); IndexResponse response = esClient.index(i -> i .index(EsConsts.BookIndex.INDEX_NAME) .id(bookInfo.getId().toString()) .document(EsBookDto.build(bookInfo)) ); log.info("Indexed with version " + response.version()); } // ... 监听其它队列,刷新其它副本数据 }
此时,如果需要更新其它小说副本数据,只需要配置更新队列和增加监听器,不需要在小说信息变更的地方增加任何业务代码,而且任意小说副本的数据刷新之间互不影响,真正实现了模块间的解耦。
Recommend
-
292
公司去年开始使用dotnet core开发项目。公司的总体架构采用的是微服务,那时候由于对微服务的理解并不是太深,加上各种组件的不成熟,只是把项目的各个功能通过业务层面拆分,然后通过nginx代理,项目最终上线。但是这远远没达到微服务的要求,其中服务治理,断路器...
-
40
目录: Maven DirectoryStructure Extensions PageElements Howto debug UnitTest Questions 今天主要想跟大家分享Jenkins插件的开发;以及关于开源的内容,个人觉得开源这件...
-
14
谈到人工智能、机器学习,我们可能会觉得很神秘,其实机器学习背后的理论并不复杂。就如同原子弹这么尖端的科技,其背后的理论就是一个很简单的公式: E = mc² 机器学习的最基础理论其实也不复杂,本文先尝试从一个线性回归问题出发,...
-
10
68篇干货,手把手教你通关 Spring Security! Spring Security 系列前前后后整了 68 篇文章了,是时候告一个段落了。 这两天松哥抽空把该系...
-
8
Electron 是一个基于 chromium 和 nodejs,可以使用 HTML、CSS、和 JavaScript 构建跨平台应用的技术框架,兼容 Mac、Windows 和 Linux。虽然 B/S 是膜前开发 ad 主流,但是 C/S 仍然有很大的市场需求。 受限于浏览器的沙盒限制...
-
5
20 天前 SSM ...
-
7
让我手把手教你写一个强大、方便使用的 IOC 容器 程序人家 posts - 173, comments - 414, views - 105万
-
4
手把手教你开发一个浏览器翻译插件发布于 9 月 16 日最近在研究一些比较有意思的东西,前几天玩了一个微信聊天机器人,美化图片的,今天想写个浏览器插件。话不多说...
-
9
2020.04.13 — Microsoft Power Automate, Automation, Rss — 1 分钟阅读之前一直...
-
3
在前面的文章中,我们提到了使用netty构建tcp和udp的客户端向已经公布的DNS服务器进行域名请求服务。基本的流程是借助于netty本身的NIO通道,将要查询的信息封装成为DNSMessage,通过netty搭建的channel发送到服务器端,然后从服务器端接受返回数据,将其编码为DNSRes...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK