最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在Spring Boot中使用Redis发布订阅功能_配置RedisMessageListenerContainer
时间:2026-07-11 09:49:57 编辑:袖梨 来源:一聚教程网
RedisMessageListenerContainer 必须手动声明 Bean,Spring Boot 2.0+ 不自动配置;监听器需实现 MessageListener 并通过 addMessageListener() 注册,不可用 @EventListener;序列化需与发布端一致,推荐统一使用 StringRedisTemplate。
RedisMessageListenerContainer 配置必须手动声明 Bean
Spring Boot 2.0+ 默认不自动配置 RedisMessageListenerContainer,哪怕你引入了 spring-boot-starter-data-redis 并配好了 RedisConnectionFactory。不显式定义这个 Bean,@EventListener 或监听器类根本不会被注册,订阅行为静默失效。
常见错误现象:RedisMessageListenerContainer 没有启动日志(如 “Starting RedisMessageListenerContainer”),发布消息后监听器无任何响应,也没有报错。
正确做法是手动声明 Bean,并确保它依赖已配置的 RedisConnectionFactory:
@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.setTaskExecutor(new ThreadPoolTaskExecutor()); // 避免阻塞主线程 return container;}
监听器注册要用 addMessageListener(),不是 @EventListener
Spring 的 @EventListener 只适用于 Spring 事件(ApplicationEvent),对 Redis 发布/订阅消息完全无效。必须通过 RedisMessageListenerContainer.addMessageListener() 显式注册监听器实例。
典型误区:写一个带 @Component 和 @EventListener 的类,以为能收到 Redis 消息——结果永远收不到。
实操建议:
- 监听器需实现
MessageListener接口(或继承KeyExpirationEventMessageListener等子类) - 用
PatternTopic订阅通配符频道(如PatternTopic("user:*")),用ChannelTopic订阅精确频道(如ChannelTopic("user.login")) - 注册时传入监听器实例和 Topic 列表,例如:
container.addMessageListener(myListener, new ChannelTopic("order.created"))
消息序列化问题常导致 onMessage() 收到 null 或乱码
默认 RedisMessageListenerContainer 使用 JdkSerializationRedisSerializer,但如果你的生产者用的是 StringRedisTemplate(即 StringRedisSerializer),两边序列化方式不一致,onMessage(Message, byte[]) 中的 message.getBody() 会是乱码或空字节数组。
解决方案取决于你的使用场景:
- 统一用
StringRedisTemplate:配置容器时设置setTopicSerializer(new StringRedisSerializer())(注意:该方法仅在 Spring Data Redis 2.6+ 可用) - 降级兼容老版本:自定义
MessageListener,在onMessage()内手动用new String(message.getBody(), StandardCharsets.UTF_8)解码 - 避免混用:不要让
RedisTemplate和StringRedisTemplate对同一组频道收发消息
发布端必须用 RedisTemplate 或 StringRedisTemplate 的 convertAndSend()
不能用 execute() + 原生 PUBLISH 命令绕过序列化逻辑,否则监听器收到的消息体无法被反序列化(尤其当容器配置了非默认序列化器时)。
正确发布方式只有两个:
-
redisTemplate.convertAndSend("channel.name", "hello")—— 要求redisTemplate的 value serializer 与监听器解码方式匹配 -
stringRedisTemplate.convertAndSend("channel.name", "hello")—— 最简单,推荐用于纯字符串消息
容易忽略的一点:convertAndSend() 是异步非阻塞的,但若连接池耗尽或 Redis 不可用,它会抛出 RedisConnectionFailureException,需在外层捕获并处理,而不是假设“发了就一定到”。
相关文章
- 王者荣耀世界连结系统怎么样 07-29
- 空洞骑士丝之歌深渊物品有哪些 07-29
- 少儿趣配音app如何添加收货地址 07-29
- 三国天下归心袁绍英雄玩法 袁绍英雄玩法攻略 07-29
- 西行乱斗八仙班变脸流玩法攻略 07-29
- 三国天下归心蔡文姬英雄玩法 蔡文姬英雄玩法攻略 07-29