【spring指南系列】使用Redis进行消息传递

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

What you’ll build

你将构建一个使用StringRedisTemplate来发布一个字符串消息的应用程序,并且有一个POJO使用MessageListenerAdapter来订阅。

**使用Spring Data Redis作为发布消息的手段可能听起来很奇怪,但是你会发现,Redis不仅提供了NoSQL数据存储,还提供了一个消息系统.

What you’ll need

  • 约15分钟

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

  • JDK 1.8或更高版本

  • Gradle 2.3+Maven 3.0+

  • 您也可以从本指南导入代码,以及直接在Spring Tool Suite(STS)中查看网页,并从那 里开始工作 。

  • Redis服务器(安装说明如下)

How to complete this guide

与大多数[Spring 入门指南]一样(Spring Guides),您可以从头开始并完成每个步骤,也可以绕过已经熟悉的基本设置步骤。 无论如何,你最终得到工作代码。

当你做完这一切, 你可以根据 gs-messaging-redis/complete中的代码检查结果.

Build with Gradle

首先你设置一个基本的构建脚本。 你可以使用任何你喜欢的一个来构建项目,当使用Spring构建应用程序时,但是需要使用GradleMaven 来写你的代码。 如果你不熟悉任何一个,请参考使用Gradle构建Java项目使用Maven构建Java项目

Create the directory structure

在您选择的项目目录中,创建以下子目录结构; 例如,在* nix*系统上使用`mkdir -p src / main / java / hello’:

└── src
    └── main
        └── java
            └── hello

Create a Gradle build file

下面是 initial Gradle build file.build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

jar {
    baseName = 'gs-messaging-redis'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter")
    compile("org.springframework.boot:spring-boot-starter-redis")
    testCompile("junit:junit")
}

Spring Boot gradle插件提供了许多方便的功能:

  • 它收集类路径上的所有jar,并构建一个单独的,可运行的“über-jar”,这使得执行和传递服务更加方便。

  • 它搜索public static void main()方法来标记为可运行类。

  • 它提供了一个内置的依赖解析器,设置版本号匹配Spring Boot dependencies. 你可以覆盖任何你想要的版本,但它会默认为Boot的选择的版本集。

Build with Maven

首先你设置一个基本的构建脚本。 你可以使用任何你喜欢的一个来构建项目,当使用Spring构建应用程序,但是需要使用Maven来构建你的代码。 如果你不熟悉Maven,请参考使用Maven构建Java项目.

Create the directory structure

在您选择的项目目录中,创建以下子目录结构; 例如,在* nix*系统上使用`mkdir -p src / main / java / hello’:

└── src
    └── main
        └── java
            └── hello

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-messaging-redis</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.3.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
</project>

Spring Boot Maven插件 提供了许多方便的功能:

  • 它收集类路径上的所有jar,并构建一个单独的,可运行的“über-jar”,这使得执行和运输服务更加方便。

  • 它搜索public static void main()方法来标记为可运行类。

  • 它提供了一个内置的依赖解析器,设置版本号匹配Spring Boot dependencies. 你可以覆盖任何你想要的版本,但它会默认为Boot的选择的版本集。

Build with your IDE

Standing up a Redis server

在您可以构建消息传递应用程序之前,您需要设置将要处理接收和发送消息的服务器。

Redis是一个开源的,BSD许可的键值数据存储,它还带有一个消息系统。 服务器在Redis 上免费提供。 你可以手动下载,或者如果你使用Mac的homebrew:

brew install redis

解压缩Redis后,您可以使用默认设置启动它。

redis-server

您应该看到这样的消息:

[35142] 01 May 14:36:28.939 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
[35142] 01 May 14:36:28.940 * Max number of open files set to 10032
                _._
              _.-``__ ''-._
        _.-``    `.  `_.  ''-._           Redis 2.6.12 (00000000/0) 64 bit
    .-`` .-```.  ```\/    _.,_ ''-._
  (    ' , .-` | `, ) Running in stand alone mode  |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379  | `-._ `._ / _.-'    |     PID: 35142
    `-._    `-._  `-./  _.-' _.-'
  |`-._`-._    `-.__.-' _.-'_.-'|  | `-._`-._ _.-'_.-' | http://redis.io  `-._ `-._`-.__.-'_.-' _.-'
  |`-._`-._    `-.__.-' _.-'_.-'|  | `-._`-._ _.-'_.-' |  `-._ `-._`-.__.-'_.-' _.-'
        `-._    `-.__.-' _.-'
            `-._        _.-'  `-.__.-'

[35142] 01 May 14:36:28.941 # Server started, Redis version 2.6.12
[35142] 01 May 14:36:28.941 * The server is now ready to accept connections on port 6379

Create a Redis message receiver

在任何基于消息的应用程序中,有消息发布者和消息接收者。 要创建消息接收器,请使用响应消息的方法实现一个接收器:src/main/java/hello/Receiver.java

package hello;

import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class Receiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);

    private CountDownLatch latch;

    @Autowired
    public Receiver(CountDownLatch latch) {
        this.latch = latch;
    }

    public void receiveMessage(String message) {
        LOGGER.info("Received <" + message + ">");
        latch.countDown();
    }
}

Receiver是一个简单的POJO,它定义了一个接收消息的方法。 正如你在注册Receiver作为消息侦听器时所看到的,你可以将消息处理方法命名为任何你想要的。

**为了演示的目的,它由具有倒计时锁存器(CountDownLatch,这个不清楚的可以谷歌一下,并发编程经常用的东西)的构造函数自动装配。 这样,它可以在它接收到消息时发出信号.

Register the listener and send a message

Spring Data Redis提供了使用Redis发送和接收消息所需的所有组件。 具体来说,你需要配置:

  • 连接工厂(connection factory)

  • 消息侦听器容器( message listener container)

  • Redis模板(Redis template)

你将使用Redis模板发送消息,使用消息侦听器容器注册“Receiver”,以便它将接收消息。 连接工厂驱动模板和消息侦听器容器,使它们能够连接到Redis服务器。

这个例子使用Spring Boot的默认RedisConnectionFactory,一个JedisConnectionFactory的实例,它基于Jedis Redis库。 连接工厂被注入到消息侦听器容器和Redis模板中。

src/main/java/hello/Application.java

package hello;

import java.util.concurrent.CountDownLatch;

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 Application {

	private static final Logger LOGGER = LoggerFactory.getLogger(Application.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(CountDownLatch latch) {
		return new Receiver(latch);
	}

	@Bean
	CountDownLatch latch() {
		return new CountDownLatch(1);
	}

	@Bean
	StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
		return new StringRedisTemplate(connectionFactory);
	}

	public static void main(String[] args) throws InterruptedException {

		ApplicationContext ctx = SpringApplication.run(Application.class, args);

		StringRedisTemplate template = ctx.getBean(StringRedisTemplate.class);
		CountDownLatch latch = ctx.getBean(CountDownLatch.class);

		LOGGER.info("Sending message...");
		template.convertAndSend("chat", "Hello from Redis!");

		latch.await();

		System.exit(0);
	}
}

在listenerAdapter方法中定义的bean作为参数,并在container中定义的消息侦听器容器中注册为消息侦听器,并将在“chat”主题上侦听消息。因为Receiver类是一个POJO,它需要被包装在一个消息监听器适配器中,该适配器实现addMessageListener()所需的MessageListener接口。消息侦听器适配器还配置为在消息到达时调用Receiver’上的receiveMessage()`方法。

连接工厂和消息监听器容器bean都是你用来监听消息的。要发送消息,您还需要一个Redis模板。这里,它是一个配置为StringRedisTemplate的bean,是RedisTemplate的一个实现,它专注于Redis的常见用法,其中键和值都是String。

main()方法通过创建一个Spring应用程序上下文来处理所有事情。应用程序上下文然后启动消息侦听器容器,消息侦听器容器bean开始侦听消息。 main()方法然后从应用程序上下文中检索StringRedisTemplate bean(其实就是IOC里的DL),并使用它在 “chat”主题下发送“Hello from Redis!”消息。最后,它关闭Spring应用程序上下文,应用程序结束。

Build an executable JAR

您可以使用Gradle或Maven从命令行运行应用程序。 或者,您可以构建单个可执行文件,其中包含所有必需的依赖关系,类和资源,并运行它。 这使得在整个开发生命周期中,易于跨不同环境将服务作为应用程序进行发布,维护版本和部署等等。

如果您使用Gradle,可以使用./gradlew bootRun运行应用程序。 或者你可以使用./gradlew build来构建JAR文件。 然后可以运行JAR文件:

java -jar build/libs/gs-messaging-redis-0.1.0.jar

如果您使用Maven,可以使用./mvnw spring-boot:run运行应用程序。 或者你可以用./mvnw clean package构建JAR文件。 然后可以运行JAR文件:

java -jar target/gs-messaging-redis-0.1.0.jar

**上面的过程将创建一个可运行的JAR。 您也可以选择
build a classic WAR file

您应该看到类似下面的输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.3.RELEASE)

2014-04-18 08:03:34.032  INFO 47002 --- [           main] hello.Application                        : Starting Application on retina with PID 47002 (/Users/gturnquist/src/spring-guides/gs-messaging-redis/complete/target/classes started by gturnquist)
2014-04-18 08:03:34.062  INFO 47002 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7a53c84a: startup date [Fri Apr 18 08:03:34 CDT 2014]; root of context hierarchy
2014-04-18 08:03:34.326  INFO 47002 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2014-04-18 08:03:34.357  INFO 47002 --- [           main] hello.Application                        : Started Application in 0.605 seconds (JVM running for 0.899)
2014-04-18 08:03:34.357  INFO 47002 --- [           main] hello.Application                        : Sending message...
2014-04-18 08:03:34.370  INFO 47002 --- [    container-2] hello.Receiver                           : Received <Hello from Redis!>
2014-04-18 08:03:34.379  INFO 47002 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7a53c84a: startup date [Fri Apr 18 08:03:34 CDT 2014]; root of context hierarchy
2014-04-18 08:03:34.380  INFO 47002 --- [       Thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 2147483647

最后

恭喜! 你刚刚使用Spring和Redis开发了一个简单的发布和订阅应用程序。

系列回顾:

【spring指南系列】计划任务

【spring指南系列】使用RESTful Web服务

【spring 指南系列】如何更好的设计RESTful API

    原文作者:知秋z
    原文地址: https://zhuanlan.zhihu.com/p/24730685
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞