springboot Redis 动态指定订阅消息监听器messageListenner
·
springboot Redis 动态指定订阅消息监听器messageListenner
1、准备工作
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、Redis 配置
package com.cetc.protocolconversion.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.concurrent.Executors;
/**
* redis 配置
*
* @author yjm
* @date 2025年11月12日 15:56
*/
@Configuration
public class RedisConfig {
/**
* redis 订阅容器-灵活配置消息处理
*
* @param connectionFactory redis连接操作
* @return 容器
*/
@Bean
public RedisMessageListenerContainer messageListenerContainer(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
/**
* 指定redis key,value,hash的序列化器
*
* @param factory redisTemplate工厂类
* @return redisTemplate
*/
@Bean
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setConnectionFactory(factory);
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setHashValueSerializer(stringRedisSerializer);
return template;
}
}
3、Redis 动态订阅工具类
package com.cetc.protocolconversion.utils;
import com.cetc.protocolconversion.config.DynamicRedisMessageListener;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* redis 订阅发布管理
*
* @author yjm
* @date 2025年12月29日 20:02
*/
@Component
public class RedisPubSubUtil {
/*线程安全的订阅发布容器*/
private final Map<String, DynamicRedisMessageListener> pubSubMap = new ConcurrentHashMap<>();
@Resource
RedisMessageListenerContainer listenerContainer;
/**
* 指定订阅处理器
*
* @param channel 主题
* @param handler 指定消息接收处理
*/
public void subscribe(String channel, DynamicRedisMessageListener.MessageHandler handler) {
DynamicRedisMessageListener messageListener = new DynamicRedisMessageListener();
messageListener.setMessageHandler(handler);
listenerContainer.addMessageListener(messageListener, new ChannelTopic(channel));
pubSubMap.put(channel, messageListener);
}
/**
* 取消订阅发布
*
* @param channel 主题
*/
public void unsubscribe(String channel) {
DynamicRedisMessageListener listener = pubSubMap.get(channel);
if (null == listener) {
return;
}
Topic topic = new ChannelTopic(channel);
listenerContainer.removeMessageListener(listener, topic);
pubSubMap.remove(channel);
}
/**
* 列出所有channel
*
* @return channel set
*/
public Set<String> listChannels() {
return pubSubMap.keySet();
}
}
4、Redis 消息监听器
package com.cetc.protocolconversion.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
/**
* 动态redis消息监听
*
* @author yjm
* @date 2025年12月29日 17:53
*/
@Slf4j
public class DynamicRedisMessageListener implements MessageListener {
private volatile MessageHandler messageHandler;
public interface MessageHandler {
void handle(String channel, String message);
}
@Override
public void onMessage(Message message, byte[] bytes) {
String channel = new String(message.getChannel());
String msg = new String(message.getBody());
if (messageHandler != null) {
messageHandler.handle(channel, msg);
} else {
log.info("默认处理:频道[{}]:{}", channel, msg);
}
}
//设置动态处理器
public void setMessageHandler(MessageHandler messageHandler) {
this.messageHandler = messageHandler;
}
}
5、测Redis监听器类测试实现类
package com.cetc.protocolconversion.config.redismsglistencer;
import com.cetc.protocolconversion.config.DynamicRedisMessageListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author yjm
* @date 2026年01月07日 16:12
*/
@Component
@Slf4j
public class TestHandlerImpl implements DynamicRedisMessageListener.MessageHandler {
public static final String TEST_CHANNEL = "TEST";
@Override
public void handle(String channel, String message) {
log.info(channel + "-:-" + message);
}
}
6、测试指定监听器订阅
@Resource
RedisPubSubUtil redisPubSubUtil;
@Resource
TestHandlerImpl testHandler;
redisPubSubUtil.subscribe("TEST_CHANNEL", testHandler)
7 、测试发布
@Resource
RedisPubSubUtil redisPubSubUtil;
redisUtil.publish("TEST_CHANNEL", "这就是个测试");
8、结果
按照TestHandlerImpl 类中所写,那就是测试发布类中发布一次,那就会打印一次:
TEST_CHANNEL:这就是个测试
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)