Redis學習筆記(四):發佈訂閱

API

  1. publish

    發佈命令,publish channel message

    PUBLISH sohu "hello world!"
    

    返回值是訂閱者的數量。

  2. subscribe

    訂閱命令

    SUBSCRIBE sohu
    

    此時處於監聽狀態,一旦有新的消息發佈,可以收到並展示。

  3. unsubscribe

    取消訂閱,其實在退出當前客戶端時就自動取消訂閱了。

    UNSUBSCRIBE [channel [channel ...]]
    

    退訂一個或多個頻道,如果執行時沒有給定任何頻道,那麼退訂所有頻道。

  4. psubscribe

    訂閱與給定模式相匹配的所有頻道

    #PSUBSCRIBE pattern [pattern ...]
    PSUBSCRIBE s*
    
  5. punsubscribe

    退訂指定的模式

    #PUNSUBSCRIBE pattern [pattern ...]
    PUNSUBSCRIBE s*
    
  6. PUBSUB

      # 列出至少有一個訂閱者的頻道
      PUBSUB CHANNELS
      # NUMSUB [channel-1 .. channel-N] 
      # 列出給定頻道(sohu)的訂閱者數量
      PUBSUB NUMSUB sohu
      # 列出所有通過模式匹配方式的訂閱者數量,沒有參數
      PUBSUB NUMPAT
    

    注意,模式匹配和指定頻道的匹配是分開統計的,雖然PSUBSCRIBE s*也能訂閱到sohu,但是PUBSUB NUMSUB sohu並不能統計到。同樣的,PUBSUB NUMPAT不能統計SUBSCRIBE sohu的數量。

Jedis演示

public class RedisSub extends JedisPubSub {

    public static void main(String[] args) throws InterruptedException {
        RedisSub redisSub = new RedisSub();
        JedisPool jedisPool = new JedisPool();
        Runnable runnable = () -> jedisPool.getResource().subscribe(redisSub, "programmer");
        new Thread(runnable).start();
        TimeUnit.SECONDS.sleep(1);
        jedisPool.getResource().publish("programmer", "a");
        TimeUnit.SECONDS.sleep(1);
        jedisPool.getResource().publish("programmer", "b");
        TimeUnit.SECONDS.sleep(4);
        redisSub.unsubscribe("programmer");
    }

    @Override
    public void onMessage(String channel, String message) {
        System.out.println("收到來自" + channel + "頻道的消息" + message);
    }

    @Override
    public void onUnsubscribe(String channel, int subscribedChannels) {
        System.out.println("退訂來自" + channel + "頻道的消息");
    }
}

輸出如下:

收到來自programmer頻道的消息a
收到來自programmer頻道的消息b
退訂來自programmer頻道的消息

Springboot集成

參考spring boot集成redis的基本配置配置Gradle依賴及連接池.

發佈

直接使用RedisTemplate::convertAndSend發佈.

訂閱

Springboot中使用發佈訂閱模式比較簡單,只需要繼承MessageListenerAdapter,通過RedisMessageListenerContainer綁定指定的一個或多個Topic(ChannelTopic或者PatternTopic)後,重寫onMessage方法來自定義業務操作.最終將組件注入到容器中即可發揮作用.非常容易擴展.

這裏以自定義的總監聽(RedisCommonMsgListener)和登錄監聽(RedisUserMsgListener)爲例.

RedisCommonMsgListener:

@Slf4j
@Component
public class RedisCommonMsgListener extends MessageListenerAdapter {
    @Autowired
    public RedisCommonMsgListener(RedisMessageListenerContainer messageListenerContainer) {
        messageListenerContainer.addMessageListener(this, new PatternTopic("*"));
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        log.info("接收到Redis的消息:{}", new String(message.getBody()));
    }
}

RedisUserMsgListener:

@Slf4j
@Component
public class RedisUserMsgListener extends MessageListenerAdapter {

    @Autowired
    public RedisUserMsgListener(RedisMessageListenerContainer messageListenerContainer) {
        LinkedList<Topic> topics = new LinkedList<Topic>() {{
            add(new ChannelTopic("swb:user:login"));
            add(new ChannelTopic("swb:user:logout"));
        }};
        messageListenerContainer.addMessageListener(this, topics);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String name = new String(message.getBody());
        String topic = new String(pattern);
        String option = null;
        if ("swb:user:login".equals(topic)) {
            option = "登錄";
        }
        if ("swb:user:logout".equals(topic)) {
            option = "退出";
        }
        log.info("user[{}]{}了系統.", name, option);
    }
}

參考

Redis實戰——Redis的pub/Sub(訂閱與發佈)在java中的實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章