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();
    }
}
相关推荐
Dragon online2 小时前
数据分析师成长之路--从SQL恐惧到数据掌控者的蜕变
数据库·sql
VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue音乐管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
一招定胜负3 小时前
navicat连接数据库&mysql常见语句及操作
数据库·mysql
热心市民蟹不肉3 小时前
黑盒漏洞扫描(三)
数据库·redis·安全·缓存
chian_ocean3 小时前
openEuler集群 Chrony 时间同步实战:从零构建高精度分布式时钟体系
数据库
Databend3 小时前
构建海量记忆:基于 Databend 的 2C Agent 平台 | 沉浸式翻译 @ Databend meetup 上海站回顾及思考
数据库
αSIM0V4 小时前
数据库期末重点
数据库·软件工程
2301_800256114 小时前
【第九章知识点总结1】9.1 Motivation and use cases 9.2 Conceptual model
java·前端·数据库
不会写程序的未来程序员4 小时前
Redis 的核心机制(线程模型、原子性、Bigkey、单线程设计原因等)
数据库·redis
编程圈子4 小时前
灵动微MM32 芯片串口升级OTA功能开发5. 写入FLASH与跳转功能
数据库