springboot中使用redis发布订阅

目录

前言

一、了解下发布订阅模式

二、通过redis-cli命令subscribe/publish体验下发布订阅

1.多个客户端订阅同一个channel

2.一个客户端订阅多个频道

三、在springboot中使用发布订阅

四、springboot中使用发布订阅的另一种写法


前言

这篇记录一下redis的发布订阅模式的简单使用,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!

一、了解下发布订阅模式

借用菜鸟教程上的描述,Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。Redis 客户端可以订阅任意数量的频道。

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

同样的,一个客户端也可以订阅多个频道。

二、通过redis-cli命令subscribe/publish体验下发布订阅

1.多个客户端订阅同一个channel

如上,打开三个命令窗口,其中两个窗口中执行命令subscribe channel1 订阅同一个频道channel1,另一个窗口中通过publish命令想channel1中发布消息aaa,可以看到另两个窗口中都接受到了消息。

2.一个客户端订阅多个频道

如上,打开三个窗口,在一个窗口中执行命令subscribe channel1 channel2 同时订阅两个频道,在另外两个窗口中分别通过publish命令向channel1和channel2中发送消息,可以看到窗口1中接受到了订阅频道中的aaa,bbb消息。

3.发布订阅相关的其它命令

1.psubscribe pattern [pattern ...]---可以订阅一个或多个符合给定模式的频道

2.punsubscribe channel [channel ...]---退订指定的频道

3.punsubscribe pattern [pattern ...]---退订所有给定模式的频道

三、在springboot中使用发布订阅

先说下在springboot中使用redis的发布订阅的步骤:

  1. 配置消息监听类(实现MessageListener接口,重写onMessage方法)。
  2. 添加监听容器(配置RedisMessageListenerContainer的bean)。
  3. 订阅频道。
  4. 向频道发布消息。

首先,贴一下消息监听类的代码:

@Component
public class RedisMessageListener implements MessageListener {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 获取消息
        byte[] messageBody = message.getBody();
        // 使用值序列化器转换
        Object msg = redisTemplate.getValueSerializer().deserialize(messageBody);
        // 获取监听的频道
        byte[] channelByte = message.getChannel();
        // 使用字符串序列化器转换
        Object channel = redisTemplate.getStringSerializer().deserialize(channelByte);
        // 渠道名称转换
        String patternStr = new String(pattern);
        System.out.println(patternStr);
        System.out.println("---频道---: " + channel);
        System.out.println("---消息内容---: " + msg);
    }
}

然后,在RedisConfig中配置一些监听容器并订阅频道,代码如下:

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                                   RedisMessageListener listener
    ) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        //订阅频道redis.news 和 redis.life  这个container 可以添加多个 messageListener
        container.addMessageListener(listener, new ChannelTopic("redis.life"));
        container.addMessageListener(listener, new ChannelTopic("redis.news"));
        return container;
    }

测试一下,使用redisTemplate的convertAndSend方法向指定频道发布消息,代码如下:

    @Test
    public void publish() {
        // 使用convertAndSend方法向频道redisChat发布消息
        redisTemplate.convertAndSend("redis.life", "aaa");
        redisTemplate.convertAndSend("redis.news", "bbb");
    }

执行测试方法publish的结果如下:

在配置监听容器添加订阅频道时,除了使用ChannelTopic外,还可以使用通配符的形式订阅一类频道,如可以通过订阅redis.*同时订阅redis.life和redis.news,代码如下:

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                                   RedisMessageListener listener
    ) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        container.addMessageListener(listener,  patternTopic());
        return container;
    }

    /**
     * 订阅匹配的多个频道
     */
    @Bean
    public PatternTopic patternTopic() {
        return new PatternTopic("redis.*");
    }

四、springboot中使用发布订阅的另一种写法

除了上面那种配置监听容器的方式之外,还可以使用MessageListenerAdapter作为参数,然后再自定义个一个消息接收类(MessageReceiver)的方式实现发布订阅。

首先,定义 一个消息接受类,代码如下:

@Component
public class MessageReceiver {
    public void receiveMessage(String message,String channel){
        System.out.println("---频道---: " + channel);
        System.out.println("---消息内容---: " + message);
    }
}

然后,配置一个MessageListenerAdapter 

    /**
     * 这个地方 是给messageListenerAdapter 传入一个消息接受的处理器,利用反射的方法调用“receiveMessage”
     * 也有好几个重载方法,这边默认调用处理器的方法 叫handleMessage 可以自己到源码里面看
     * @param receiver
     * @return
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(MessageReceiver receiver) {
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

最后,修改下监听容器,RedisMessageListener替换为MessageListenerAdapter,代码如下:

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                                   MessageListenerAdapter adapter
    ) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        // 一次订阅多个匹配的频道
        container.addMessageListener(adapter, patternTopic());
        return container;
    }

<think>好的,用户想在Spring Boot中集成Redis实现发布订阅功能。首先,我需要回忆一下Spring Data Redis的相关知识。记得Redis发布订阅模式需要配置消息监听容器和消息监听器。用户可能需要具体的代码示例和配置步骤。 首先,应该从添加依赖开始,比如Spring Boot Starter Data Redis。然后配置Redis连接信息,比如主机、端口、密码等,这些通常在application.properties里设置。接下来,需要定义消息监听容器和适配器,可能使用RedisMessageListenerContainer和ChannelTopic。 然后,用户需要创建发布消息的服务,使用RedisTemplateconvertAndSend方法。订阅方面,需要实现MessageListener接口或者使用注解@RedisListener,不过Spring Data Redis好像没有这个注解,可能需要通过配置监听容器来添加订阅的频道。 还需要考虑多线程消费的问题,参考用户提供的引用链接中有提到多线程消费和线程池配置,可能需要设置TaskExecutor来并行处理消息。另外,序列化方式也很重要,默认的JDK序列化可能不友好,建议使用StringRedisSerializer或者JSON序列化。 用户可能还会遇到频道通配符的问题,比如使用PSUBSCRIBE来订阅模式匹配的频道,这时候可能需要使用PatternTopic代替ChannelTopic。另外,异常处理也是需要注意的地方,比如连接失败时的处理机制。 需要检查用户提供的引用链接,特别是优快云和Stack Overflow的那些,看看有没有最佳实践或常见问题解答。例如,某个链接提到并行消费和线程池配置,这可能涉及到调整监听容器的并发设置。另一个链接讨论了多主题订阅,可能需要配置多个消息监听器或使用通配符。 总结下来,步骤大致是:添加依赖、配置连接、设置消息监听容器、实现监听器、创建发布服务,以及考虑序列化和并发处理。在回答中需要提供代码示例,确保LaTeX格式正确,同时生成相关问题引导用户进一步学习。</think>### Spring Boot集成Redis发布订阅功能分步指南 #### 一、环境准备 1. 添加Maven依赖(Spring Boot 2.7.x) ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置application.yml ```yaml spring: redis: host: localhost port: 6379 password: yourpassword lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 ``` #### 二、核心配置类 ```java @Configuration @EnableCaching public class RedisConfig { @Bean public RedisMessageListenerContainer redisContainer(RedisConnectionFactory factory, MessageListenerAdapter listenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(factory); container.addMessageListener(listenerAdapter, new ChannelTopic("news_channel")); container.setTaskExecutor(taskExecutor()); // 设置线程池[^2] return container; } @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(25); return executor; } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` #### 三、消息监听器实现 ```java @Component public class NewsSubscriber implements MessageListener { private static final Logger logger = LoggerFactory.getLogger(NewsSubscriber.class); @Override public void onMessage(Message message, byte[] pattern) { String channel = new String(message.getChannel()); String body = new String(message.getBody()); logger.info("Received [{}] from [{}]", body, channel); } } ``` #### 四、消息发布服务 ```java @Service public class NewsPublisher { private final RedisTemplate<String, Object> redisTemplate; @Autowired public NewsPublisher(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } public void publishNews(String message) { redisTemplate.convertAndSend("news_channel", message); } } ``` #### 五、使用示例 ```java @RestController @RequestMapping("/news") public class NewsController { private final NewsPublisher publisher; @Autowired public NewsController(NewsPublisher publisher) { this.publisher = publisher; } @PostMapping public ResponseEntity<String> postNews(@RequestBody String content) { publisher.publishNews(content); return ResponseEntity.ok("Message published"); } } ``` #### 高级特性配置 1. **通配符订阅**: ```java // 在RedisConfig中添加 container.addMessageListener(listenerAdapter, new PatternTopic("sensor.*")); ``` 2. **消息序列化优化**: ```java // 配置专用String模板 @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(factory); template.setValueSerializer(new GenericToStringSerializer<>(String.class)); return template; } ``` #### 常见问题排查 1. 消息未接收:检查`@Bean`注入顺序和频道名称一致性 2. 序列化异常:确保发布/订阅端使用相同序列化方式 3. 连接超时:验证防火墙设置和Redis服务状态
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值