本指南将引导您完成使用 Spring Data Redis 发布和订阅通过 Redis 发送的消息的过程。
你将构建什么
您将构建一个应用程序,该应用程序使用 StringRedisTemplate
发布字符串消息,并通过 MessageListenerAdapter
让一个 POJO 订阅该消息。
使用 Spring Data Redis 作为发布消息的方式可能听起来有些奇怪,但您会发现,Redis 不仅提供了一个 NoSQL 数据存储,还提供了一个消息系统。
所需内容
-
大约15分钟
-
一个喜欢的文本编辑器或IDE
-
Java 17 或更高版本
如何完成本指南
与大多数 Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以直接查看此仓库中的代码来跳转到解决方案。
要在本地环境中查看最终结果,您可以执行以下操作之一:
- 下载并解压本指南的源代码仓库
- 使用 Git 克隆仓库:
git clone https://github.com/spring-guides/gs-messaging-redis.git
- Fork 该仓库,以便您可以通过提交拉取请求来请求对本指南的更改
设置 Redis 服务器
在构建消息传递应用程序之前,您需要设置用于处理接收和发送消息的服务器。本指南假设您使用 Spring Boot Docker Compose支持。此方法的前提是您的开发机器上有一个 Docker 环境,例如 Docker Desktop。添加一个 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。
- 点击 Dependencies,然后选择 Spring Data Redis 和 Docker Compose Support。
- 点击 Generate。
- 下载生成的 ZIP 文件,这是一个根据您的选择配置好的应用程序归档文件。
如果您的 IDE 集成了 Spring Initializr,您可以直接在 IDE 中完成这个过程。
创建 Redis 消息接收器
在任何基于消息传递的应用程序中,都有消息发布者和消息接收者。要创建消息接收者,需要实现一个接收器,并提供一个方法来响应消息,如下例所示(来自 src/main/java/com/example/messagingredis/Receiver.java
):
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();
}
}
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 运行主方法。请注意,如果您从解决方案仓库克隆了项目,您的 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
。有关连接 Redis 的更多信息,请参阅 Spring Boot 文档。
构建应用程序
本节介绍运行本指南的不同方法:
-
构建并执行 JAR 文件
-
使用 Cloud Native Buildpacks 构建并执行 Docker 容器
无论您选择如何运行应用程序,输出结果应该是一致的。
要运行应用程序,您可以将应用程序打包为可执行的 jar 文件。使用 ./mvnw clean package
命令将应用程序编译为可执行的 jar 文件。然后,您可以使用 java -jar target/messaging-redis-0.0.1-SNAPSHOT.jar
命令运行该 jar 文件。
另外,如果您有可用的 Docker 环境,您可以直接通过 Maven 或 Gradle 插件使用 buildpacks 创建 Docker 镜像。使用 Cloud Native Buildpacks,您可以创建可在任何地方运行的 Docker 兼容镜像。Spring Boot 直接为 Maven 和 Gradle 提供了 buildpack 支持。这意味着您只需输入一条命令,就可以快速将合理的镜像推送到本地运行的 Docker 守护进程中。要使用 Cloud Native Buildpacks 创建 Docker 镜像,请运行 ./mvnw spring-boot:build-image
命令。在启用 Docker 环境的情况下,您可以使用 docker run --network container:guide-redis docker.io/library/messaging-redis:0.0.1-SNAPSHOT
命令运行应用程序。
--network
标志告诉 Docker 将我们的指南容器附加到外部容器正在使用的现有网络上。您可以在 Docker 文档 中找到更多信息。
总结
恭喜!您刚刚使用 Spring 和 Redis 开发了一个发布-订阅应用程序。
另请参阅
以下指南可能也会有所帮助: