使用 Redis 进行消息传递

本指南将引导您完成使用 Spring Data Redis 发布和订阅使用 Redis 发送的消息的过程。

您将构建的内容

您将构建一个应用程序,该应用程序使用StringRedisTemplate发布字符串消息,并使用MessageListenerAdapter让一个 POJO 订阅该消息。

使用 Spring Data Redis 作为发布消息的方法听起来可能很奇怪,但是,正如您将要发现的那样,Redis 不仅提供了一个 NoSQL 数据存储,还提供了一个消息系统。

您需要什么

  • 大约 15 分钟

  • 您最喜欢的文本编辑器或 IDE

  • Java 17 或更高版本

如何完成本指南

像大多数 Spring 入门指南 一样,您可以从头开始完成每个步骤,也可以通过查看此存储库中的代码直接跳转到解决方案。

在本地环境中查看最终结果,您可以执行以下操作之一

设置 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 文件。此项目已配置为适合本教程中的示例。

要手动初始化项目

  1. 导航到https://start.spring.io。此服务会引入应用程序所需的所有依赖项,并为您完成大部分设置工作。

  2. 选择 Gradle 或 Maven 以及您要使用的语言。本指南假设您选择了 Java。

  3. 单击依赖项并选择Spring Data RedisDocker Compose 支持

  4. 单击生成

  5. 下载生成的 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 运行 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.hostspring.data.redis.port分别默认为localhost6379Spring 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 开发了一个发布-订阅应用程序。

另请参阅

以下指南可能也有帮助

想编写新的指南或为现有指南贡献代码?请查看我们的 贡献指南

所有指南的代码均采用 ASLv2 许可证发布,文档采用 署名-非衍生作品创作共用许可证

获取代码