Redis_发布订阅(Spring Boot)
目录
前言
生产者和消费者
发布和订阅
Java实现
注意
转至 http://www.tianmaying.com/tutorial/springboot-redis-message
前言
利用Spring Data对Redis的支持来实现消息的发布订阅机制。
使用StringRedisTemplate来发布一个字符串消息,同时基于MessageListenerAdapter使用一个POJO来订阅和响应该消息。
Receiver类将会被注册为一个消息监听者时。给Receiver的构造函数通过@AutoWired标注注入了一个CountDownLatch实例,当接收到消息时,调用cutDown()方法。
Spring Data Redis提供基于Redis发送和接收消息的所有需要的组件,需要配置如下:
a.一个连接工厂(connection factory)
b.一个消息监听者容器(message listener container)
c.一个Redis的模板(redis template)
d.将Receiver注册给消息监听者容器。连接工厂将两者连接起来,使得它们可以通过Redis服务器通信。
实现
pom.xml
<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>com.tianmaing</groupId> <artifactId>redis-message</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>redis-message</name> <description>Demo of message processing by redis</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> <relativePath /> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <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> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties
#spring.redis.database=0
spring.redis.host=192.168.1.10
#spring.redis.password= Login password of the redis server.
#spring.redis.pool.max-active=8
#spring.redis.pool.max-idle=8
#spring.redis.pool.max-wait=-1
#spring.redis.pool.min-idle=0
spring.redis.port=6379
#spring.redis.sentinel.master= Name of Redis server.
#spring.redis.sentinel.nodes= Comma-separated list of host:port pairs.
#spring.redis.timeout=0
Receiver.java
package com.dengzy.springboot.redis; 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 + ">"); //当接收到消息时,调用cutDown()方法。 latch.countDown(); } }
app.java
package com.dengzy.springboot; 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; import com.dengzy.springboot.redis.Receiver; @SpringBootApplication public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); //listenerAdapter方法中定义的Bean注册为一个消息监听者,它将监听chat主题的消息。 @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.addMessageListener(listenerAdapter, new PatternTopic("chat")); return container; } //MessageListenerAdapter使用一个POJO来订阅和响应该消息。 @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); } //StringRedisTemplate来发送键和值均为字符串的消息。 @Bean StringRedisTemplate template(RedisConnectionFactory connectionFactory) { return new StringRedisTemplate(connectionFactory); } public static void main(String[] args) throws InterruptedException { ApplicationContext ctx = SpringApplication.run(App.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); } }
sendMsg.java
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class SendMessage { private static Logger logger = LoggerFactory.getLogger(SendMessage.class); public static final String CHANNEL_NAME = "chat"; public static void main(String[] args) throws Exception { JedisPoolConfig poolConfig = new JedisPoolConfig(); JedisPool jedisPool = new JedisPool(poolConfig, "192.168.1.10", 6379, 0); for(int i=0;i<10;i++){ try { jedisPool.getResource().publish(CHANNEL_NAME, "hello" + i); } catch (Exception e) { logger.error("Subscribing failed." + e.getMessage()); } } } }