This chapter takes you to use Spring Data Redis to implement publishing and subscribing Redis messages.
The goal of this article
Build an application with Spring Boot, use StringRedisTemplate to publish a string message, and use MessageListenerAdapter to subscribe to the message.
Using Spring Data Redis to publish messages sounds a bit strange, but you will find that Redis not only provides a NoSQL data store, but also a message system.
you need to
- about 15 minutes
- I understand the idea
- JDK 1.8+
- Maven 3.2+
- redis server
Start a Redis server
Before creating a messaging application, we need to configure a server responsible for receiving and sending messages.
Redis is an open source, based on BSD protocol, key-value storage system, with a message system.
For the installation method of the Windows version, please refer to this article Redis download and installation (windows version) .
Generate project code with Spring Initializr
For all Spring applications, you can use Spring Initializr to generate basic project code. Initializr provides a quick way to pull in all the dependencies you need, and does a lot of the setup for you. The current example requires a Spring Data Redis dependency.
The specific settings are as follows:
As shown in the figure above, we have chosen Maven as the compilation tool. You can also choose Gradle to compile. Then we set Group and Artifact to "com.hansy" and "messaging-redis" respectively.
The content of the generated pom.xml file is as follows:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hansy</groupId>
<artifactId>messaging-redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>messaging-redis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create a Redis message receiver
In any message-based application, there are message publishers and message receivers. Implement a message receiver with a method that can respond to messages. code show as below:
package com.hansy.messagingredis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.atomic.AtomicInteger;
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 is a POJO class that defines methods for receiving received messages. When you register a Receiver as a message listener, the name of the message processing method can be arbitrary.
For demonstration purposes, this Receiver just counts the number of messages received.
Register listeners and send messages
Spring Data Redis provides all the components to send and receive messages using Redis.
We need to configure the following elements:
- a connection factory
- A container for message listeners
- A Redis Template
We will use Redis Template to send messages, and register Receiver to the message listener container to receive messages. The connection factory drives the template and the container of the message listener, allowing them to connect to the Redis server.
This example uses Spring Boot's default RedisConnectionFactory, an instance of JedisConnectionFactory (based on the jedis library). This connection factory is injected into the container of the message listener and the Template of Redis, the code is as follows:
package com.hansy.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
Receiver receiver() {
return new Receiver();
}
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
}
@Bean
StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
public static void main(String[] args) throws InterruptedException {
ApplicationContext context = SpringApplication.run(MessagingRedisApplication.class, args);
StringRedisTemplate template = context.getBean(StringRedisTemplate.class);
Receiver receiver = context.getBean(Receiver.class);
while (receiver.getCount() == 0) {
logger.info("Sending message...");
template.convertAndSend("chat", "Hello from Redis!");
Thread.sleep(500L);
}
System.exit(0);
}
}
The receiver() method returns a simple Receiver object, which is wrapped into the MessageListenerAdapter returned by the listenerAdapter() method. Then add it to the RedisMessageListenerContainer through the addMessageListener() method to monitor the "chat" topic. When a message arrives, the receiveMessage() method of the Receiver object is called.
Listening to messages requires some classes such as connection factories and message listening containers. To send a message, RedisTemplate is required. We use StringRedisTemplate, an implementation class of RedisTemplate. When using Redis, both key and value are String instances.
The main() method first creates a SpringApplication context. Then the Application context starts a message listening container, and the message listening container starts listening for messages. The main() method then fetches a StringRedisTemplate object from the context, and uses the StringRedisTemplate to send a text message "Hello from Redis!" on the "chat" topic. Finally, close the SpringApplication context and the program ends.
run the program
Run the program, the result is as follows:
2020-07-30 16:45:15.548 INFO 24544 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-07-30 16:45:15.550 INFO 24544 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2020-07-30 16:45:15.576 INFO 24544 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 10ms. Found 0 Redis repository interfaces.
2020-07-30 16:45:18.077 INFO 24544 --- [ main] c.h.m.MessagingRedisApplication : Started MessagingRedisApplication in 3.157 seconds (JVM running for 6.317)
2020-07-30 16:45:18.079 INFO 24544 --- [ main] c.h.m.MessagingRedisApplication : Sending message...
2020-07-30 16:45:18.092 INFO 24544 --- [ container-2] com.hansy.messagingredis.Receiver : Received <Hello from Redis!>
summary
You have used Spring Boot to develop a program that uses Redis to complete publish and subscribe.