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();
    }
}
相关推荐
信创天地18 小时前
国产关系型数据库部署与权限管理实战:人大金仓、达梦、南大通用、华为GaussDB
数据库·华为·gaussdb
l1t19 小时前
psql 中的流水线操作(PostgreSQL 18)
数据库·人工智能·postgresql
enfpZZ小狗19 小时前
使用Flask快速搭建轻量级Web应用
jvm·数据库·python
Geek攻城猫19 小时前
深入理解 SQL 多字段排序:从基础到高级技巧
数据库·sql
洛_尘19 小时前
MySQL 7:数据库设计
数据库·mysql
heze0919 小时前
sqli-labs-Less-22
数据库·mysql·网络安全
墨雨晨曦8819 小时前
如何保证redis和mysql数据一致性方案对比
数据库·redis·mysql
枷锁—sha20 小时前
【Vulhub】Discuz! 7.2 faq.php SQL 注入深度复现手册 (转义逃逸篇)
数据库·sql·php
超级种码20 小时前
Redis:Redis 常见问题及解决思路
数据库·redis·缓存
xcLeigh20 小时前
Oracle 迁移 KingbaseES 避坑指南:工具选型、参数配置与性能调优
数据库·oracle·工具·性能·金仓·kingbasees