redis发布订阅

命令行使用发布订阅:

springboot使用发布订阅

redisTemplate.convertAndSend(channel名字,数据)

springboot中监听redis发布的内容,,有两种方式:

  • 实现MessageListener类
java 复制代码
/**
 * 实现接口  消费
 */
@Component
public class MyConsumer01 implements MessageListener {
    @Autowired
    RedisTemplate redisTemplate;


    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 消息的内容
        byte[] body = message.getBody();
        String s = new String(body);

        // 用默认的序列化器,,序列化
        Book book = (Book) redisTemplate.getValueSerializer().deserialize(body);
        System.out.println("book = " + book);
        System.out.println("s = " + s);
    }
}
  • 自定义类,,因为是自定义的类,,所以需要一个适配器把他转换成 MessageListener 才能使用
java 复制代码
@Component
public class MyConsumer02 {

    /**
     * 这个方法你想怎么写怎么写,,但是需要配置注册进去 ===》 通过一个适配器,,去适配
     * @param message
     * @param channel
     */
    public void receiveMessage(Book message, String channel){
        System.out.println("message = " + message);
    }
}

这个自定义的监听器需要通过适配器适配:

java 复制代码
  /**
     * 给自定义的 MyConsumer02 来适配
     * @return
     */
    @Bean
    MessageListenerAdapter messageListenerAdapter(){
        // 告诉他 接收消息的方法
        MessageListenerAdapter receiveMessage = new MessageListenerAdapter(myConsumer02, "receiveMessage");

        // 这个反序列化不会平白无故的转成  想要的类型 ===> 设置反序列化方式
        // 将来收到消息之后,,会通过这里设置的序列化方案,,进行反序列化
        receiveMessage.setSerializer(new GenericJackson2JsonRedisSerializer());
        return receiveMessage;
    }

想让这两个监听器生效,,还需要配置监听器,,设置这两个监听器,,去监听,,哪些通道:

java 复制代码
   @Bean
    RedisMessageListenerContainer container(MyConsumer01 myConsumer01, MessageListenerAdapter messageListenerAdapter, RedisConnectionFactory redisConnectionFactory){
        // 注册监听器
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.addMessageListener(myConsumer01,new ChannelTopic(CHANNEL_01));
        container.addMessageListener(messageListenerAdapter,new PatternTopic(CHANNEL_02));

        return container;

    }

收发对象可以定义序列化方案,,, 对象的序列化和反序列化,,一般都用GenericJackson2JsonRedisSerializer

java 复制代码
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        return redisTemplate;
    }

redisTemplate 里面有方法能直接处理二进制,,redisTemplate.getValueSerializer().deserialize(body); 可以直接将二进制按照 value的序列化器去 序列化


队列

redis中list可以做队列,,它里面有block开头的,,,阻塞队列,,,阻塞多少时间才去执行,,,

list做队列,,必须自己去通过死循环,,或者定时器,,去拉取list中的内容,,,, 他没有自己的监听器,,没法监听,,,

但是list中有一种阻塞队列,,,就是阻塞多少时间,,如果这个时间到了,,才放弃阻塞,,,这就能避免无限空死循环,,,

java 复制代码
package com.cj.pub_sub_demo.consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class MyConsumerList01 {

    @Autowired
    StringRedisTemplate redisTemplate;


    public void receive(){

        while (true){
            // 延迟获取消息
            String o = (String) redisTemplate.opsForList().rightPop("list_mq",10, TimeUnit.SECONDS);
            if (o != null){
                System.out.println("收到消息 = " + o);
            }else{
                System.out.println("111");
            }
        }

    }


    public void blockReceive() throws InterruptedException {
        // bound 之后不用绑定key
        BoundListOperations listMq = redisTemplate.boundListOps("list_mq");

        // 接下来都是绑定key的
        while (true){
            Object o = listMq.rightPop();
            if (o != null){
                System.out.println(o);
            }else{
                Thread.sleep(1000);
            }
        }

    }
}

这个队列,可以在springboot刚启动的时候,就开启这个死循环:

java 复制代码
/**
 * 1. 数据预加载 :  在启动时向数据库插入默认数据,配置信息,,或者测试数据
 * 2. 缓存预热 :从数据库加载热点数据到redis缓存中
 * 3. 资源检查: 验证外部服务,,如邮件服务器,文件存储是否可用
 * 4. 执行命令行逻辑: 对于非web应用,,如批处理任务,,在这里编写主要的业务逻辑
 * 5. 发送启动通知,通知监控系统或日志系统 已启动成功
 */
@Component

public class MyCommandRunner implements CommandLineRunner {
    @Autowired
    MyConsumerList01 myConsumerList01;
    @Override
    public void run(String... args) throws Exception {

        myConsumerList01.receive();
    }
}
相关推荐
李广坤9 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区1 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再2 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest2 天前
数据库SQL学习
数据库·sql
jnrjian2 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle
十月南城2 天前
数据湖技术对比——Iceberg、Hudi、Delta的表格格式与维护策略
大数据·数据库·数据仓库·hive·hadoop·spark