package com.example.messagingredis;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Receiver {
private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);
private AtomicInteger counter = new AtomicInteger();
public void receiveMessage(String message) {
LOGGER.info("Received <" + message + ">");
counter.incrementAndGet();
}
public int getCount() {
return counter.get();
}
}
使用 Redis 进行消息传递
本指南将引导您完成使用 Spring Data Redis 发布和订阅使用 Redis 发送的消息的过程。
您将构建的内容
您将构建一个应用程序,该应用程序使用StringRedisTemplate
发布字符串消息,并使用MessageListenerAdapter
让一个 POJO 订阅该消息。
使用 Spring Data Redis 作为发布消息的方法听起来可能很奇怪,但是,正如您将要发现的那样,Redis 不仅提供了一个 NoSQL 数据存储,还提供了一个消息系统。 |
您需要什么
-
大约 15 分钟
-
您最喜欢的文本编辑器或 IDE
-
Java 17 或更高版本
如何完成本指南
要在本地环境中查看最终结果,您可以执行以下操作之一
-
下载并解压缩本指南的源代码存储库
-
使用 Git 克隆存储库:
git clone https://github.com/spring-guides/gs-messaging-redis.git
-
派生存储库,这使您可以通过提交拉取请求来请求对此指南的更改
设置 Redis 服务器
添加一个依赖项spring-boot-docker-compose
,它执行以下操作:
-
在您的工作目录中搜索
compose.yml
和其他常见的 compose 文件名。 -
使用发现的
compose.yml
调用docker compose up
。 -
为每个受支持的容器创建服务连接 Bean。
-
当应用程序关闭时,调用
docker compose stop
。
要使用 Docker Compose 支持,您只需要遵循本指南即可。根据您引入的依赖项,Spring Boot 会找到正确的compose.yml
文件,并在您运行应用程序时启动您的 Docker 容器。
如果您选择自己运行 Redis 服务器而不是使用 Spring Boot Docker Compose 支持,则有一些选择: - 下载服务器并手动运行它 - 如果您使用的是 Mac,则可以使用 Homebrew 安装 - 使用docker compose up
手动运行compose.yaml
文件
如果您采用任何这些替代方法,则应从 Maven 或 Gradle 构建文件中删除spring-boot-docker-compose
依赖项。您还需要向application.properties
文件添加配置,这在准备构建应用程序部分中有更详细的说明。如前所述,本指南假设您在 Spring Boot 中使用 Docker Compose 支持,因此此时不需要对application.properties
进行其他更改。
从 Spring Initializr 开始
您可以使用此预初始化项目并单击“生成”以下载 ZIP 文件。此项目已配置为适合本教程中的示例。
要手动初始化项目
-
导航到https://start.spring.io。此服务会引入应用程序所需的所有依赖项,并为您完成大部分设置工作。
-
选择 Gradle 或 Maven 以及您要使用的语言。本指南假设您选择了 Java。
-
单击依赖项并选择Spring Data Redis和Docker Compose 支持。
-
单击生成。
-
下载生成的 ZIP 文件,这是一个使用您选择的选项配置的应用程序的存档。
如果您的 IDE 集成了 Spring Initializr,则可以从您的 IDE 完成此过程。 |
创建 Redis 消息接收器
在任何基于消息的应用程序中,都存在消息发布者和消息接收器。要创建消息接收器,请实现一个带有响应消息方法的接收器,如下面的示例(来自src/main/java/com/example/messagingredis/Receiver.java
)所示
Receiver
是一个 POJO,它定义了一个用于接收消息的方法。当您将Receiver
注册为消息侦听器时,您可以将消息处理方法命名为您想要的任何名称。
出于演示目的,接收器正在计算收到的消息。这样,它可以在收到消息时发出信号。 |
注册侦听器并发送消息
Spring Data Redis 提供了使用 Redis 发送和接收消息所需的所有组件。具体来说,您需要配置:
-
连接工厂
-
消息侦听器容器
-
Redis 模板
您将使用 Redis 模板发送消息,并将Receiver
与消息侦听器容器注册,以便它将接收消息。连接工厂驱动模板和消息侦听器容器,使它们能够连接到 Redis 服务器。
此示例使用 Spring Boot 的默认RedisConnectionFactory
,这是一个基于Jedis Redis 库的JedisConnectionFactory
实例。连接工厂注入到消息侦听器容器和 Redis 模板中,如下面的示例(来自src/main/java/com/example/messagingredis/MessagingRedisApplication.java
)所示
package com.example.messagingredis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
@SpringBootApplication
public class MessagingRedisApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(MessagingRedisApplication.class);
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Bean
Receiver receiver() {
return new Receiver();
}
@Bean
StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(MessagingRedisApplication.class, args);
StringRedisTemplate template = ctx.getBean(StringRedisTemplate.class);
Receiver receiver = ctx.getBean(Receiver.class);
while (receiver.getCount() == 0) {
LOGGER.info("Sending message...");
template.convertAndSend("chat", "Hello from Redis!");
Thread.sleep(500L);
}
System.exit(0);
}
}
在listenerAdapter
方法中定义的 Bean 注册为在container
中定义的消息侦听器容器中的消息侦听器,并将侦听chat
主题上的消息。因为Receiver
类是一个 POJO,所以它需要包装在一个实现MessageListener
接口(addMessageListener()
需要此接口)的消息侦听器适配器中。消息侦听器适配器还配置为在消息到达时调用Receiver
上的receiveMessage()
方法。
连接工厂和消息侦听器容器 Bean 是侦听消息所需的一切。要发送消息,您还需要一个 Redis 模板。在这里,它是一个配置为StringRedisTemplate
的 Bean,这是RedisTemplate
的一个实现,它专注于 Redis 的常用用法,其中键和值都是String
实例。
main()
方法通过创建 Spring 应用程序上下文来启动所有操作。然后,应用程序上下文启动消息侦听器容器,并且消息侦听器容器 Bean 开始侦听消息。然后,main()
方法从应用程序上下文中检索StringRedisTemplate
Bean,并使用它在chat
主题上发送Hello from Redis!
消息。最后,它关闭 Spring 应用程序上下文,应用程序结束。
运行应用程序
您可以通过 IDE 运行 main 方法。请注意,如果您已从解决方案存储库克隆了项目,则您的 IDE 可能会在错误的位置查找compose.yaml
文件。您可以配置您的 IDE 以查找正确的位置,也可以使用命令行运行应用程序。./gradlew bootRun
和./mvnw spring-boot:run
命令启动应用程序并自动查找 compose.yaml 文件。
您应该看到以下输出:
yyyy-mm-ddT07:08:48.646-04:00 INFO 18338 --- [main] c.e.m.MessagingRedisApplication: Sending message...
yyyy-mm-ddT07:08:48.663-04:00 INFO 18338 --- [container-1] com.example.messagingredis.Receiver : Received <Hello from Redis!>
准备构建应用程序
要在没有 Spring Boot Docker Compose 支持的情况下运行代码,您需要在本地运行 Redis 版本。为此,您可以使用 Docker Compose,但必须首先对compose.yaml
文件进行两次更改。首先,修改compose.yaml
中的ports
条目为'6379:6379'
。其次,添加container_name
。
compose.yaml
现在应该是:
services: redis: container_name: 'guide-redis' image: 'redis:latest' ports: - '6379:6379'
您现在可以运行docker compose up
来启动 Redis 服务器。现在,您应该有一个准备接受请求的外部 Redis 服务器。您可以重新运行应用程序,并使用您的外部 Redis 服务器查看相同的输出。
不需要在application.properties 文件中进行任何配置,因为默认值与compose.yaml 中的 Redis 服务器配置匹配。具体来说,属性spring.data.redis.host 和spring.data.redis.port 分别默认为localhost 和6379 。Spring Boot 文档中提供了有关连接到 Redis 的更多信息。 |
构建应用程序
本节描述运行本指南的不同方法
无论您选择如何运行应用程序,输出都应该相同。
要运行应用程序,您可以将应用程序打包为可执行 jar。./mvnw clean package
命令将应用程序编译为可执行 jar。然后,您可以使用java -jar target/messaging-redis-0.0.1-SNAPSHOT.jar
命令运行 jar。
或者,如果您有 Docker 环境,可以使用构建包直接从您的 Maven 或 Gradle 插件创建 Docker 镜像。使用 云原生构建包 (Cloud Native Buildpacks),您可以创建可在任何地方运行的与 Docker 兼容的镜像。Spring Boot 直接为 Maven 和 Gradle 提供构建包支持。这意味着您可以键入单个命令,并快速将一个合理的镜像放入本地运行的 Docker 守护进程中。要使用云原生构建包创建 Docker 镜像,请运行./mvnw spring-boot:build-image
命令。启用 Docker 环境后,您可以使用 docker run --network container:guide-redis docker.io/library/messaging-redis:0.0.1-SNAPSHOT
命令运行应用程序。
--network 标志告诉 Docker 将我们的 guide 容器附加到我们的外部容器正在使用的现有网络。您可以在 Docker 文档 中找到更多信息。 |
总结
恭喜!您刚刚使用 Spring 和 Redis 开发了一个发布-订阅应用程序。