對於本篇博文主要從以下兩部分介紹簡易聊天室的實現:
1.介紹redis發布訂閱模式
2.java代碼實現訂閱發布模式
一、redis發布訂閱模式
redis訂閱分為訂閱頻道和訂閱模式
1.訂閱頻道
開啟一個用戶端1,訂閱電影直播頻道:
127.0.0.1:6379> subscribe "movie::live::room"
在電影直播頻道發布資訊A
127.0.0.1:6379> publish movie::live::room "Does someone like snow white?"
在訊息發布後,訂閱訊息的用戶端1就會收到發布的資訊。如果我們想要訂閱多個頻道,可以使用訂閱模式。
2.訂閱模式
重新開啟一個啟用戶端2,並訂閱有關電影的模式:
127.0.0.1:6379> psubscribe "movie*"
此時在電影直播頻道重新發布訊息A,用戶端1和用戶端2都會收到發布的訊息。
如果在電影曆史頻道發布訊息B,
127.0.0.1:6379> publish movie::history::room "Does someone like snow white?"
此時只有用戶端2會收到訊息。
訂閱模式支援* 、? 、 []三種模式
*匹配後面所有的字元
?匹配一個字元
[]匹配中括弧裡的字元 h[eo]llo 匹配hello和hollo
二、java代碼實現訂閱發布模式
接下來使用Jedis實現一個簡單的聊天室
我們用redis作為服務轉寄,所以沒有服務端代碼,只需要寫用戶端就可以了:
定義用戶端,功能比較簡單,進入房間提示、離開房間提示、在房間說話:
package redis.publishandsubscribe;import java.util.Scanner;import redis.RedisUtil;public class Client { private String name ; private ChatSubscribe roomSubListerner; public Client(){ roomSubListerner = new ChatSubscribe(); } public void setName(String name){ this.name =name; } public String getName(){ return name; } /* 進入房間*/ public void subscribe(final String[] room){ ChatSubscribe roomSub = roomSubListerner; roomSub.setClientName(name); roomSub.setRoom(room); RedisUtil.subscribe(room, roomSub); } /* 退出房間*/ public void unSubscribe(final String[] room){ roomSubListerner.unsubscribe(room); } /*說話*/ public void say(final String room,String message){ RedisUtil.publish(room, name+" say:"+message); }}
在上面的代碼中有一個ChatSubscribe的類,該類為聊天室的動作監聽類,在這個類中我們只定義訂閱頻道、取消訂閱頻道、接收訊息方法:
package redis.publishandsubscribe;import redis.RedisUtil;import redis.clients.jedis.JedisPubSub;public class ChatSubscribe extends JedisPubSub{ /*成員名字*/ private String clientName; /*房間名*/ private String[] room; public String getClientName() { return clientName; } public void setClientName(String clientName) { this.clientName = clientName; } public String[] getRoom() { return room; } public void setRoom(String[] room) { this.room = room; } @Override public void onUnsubscribe(String channel, int subscribedChannels) { //do nothing } @Override public void onSubscribe(String channel, int subscribedChannels) { RedisUtil.publish( channel,clientName+ "進入房間"); } @Override public void onPUnsubscribe(String pattern, int subscribedChannels) { } @Override public void onPSubscribe(String pattern, int subscribedChannels) { } @Override public void onPMessage(String pattern, String channel, String message) { } @Override public void onMessage(String channel, String message) { System.out.println("收到來自"+channel+"房間的訊息:"+message); } @Override public void unsubscribe(String... channels) { for(String c : channels) RedisUtil.publish(c, clientName+"離開房間"); super.unsubscribe(channels); }}
接下來redis通用類的編寫:
package redis;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.JedisPubSub;public class RedisUtil { private static JedisPool jedisPool; private RedisUtil(){ } static { JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxIdle(5); poolConfig.setMinIdle(1); poolConfig.setTestOnBorrow(true); poolConfig.setNumTestsPerEvictionRun(10); poolConfig.setTimeBetweenEvictionRunsMillis(60000); poolConfig.setMaxWaitMillis(10000); jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379); } private static void returnResource(Jedis jedis) { jedisPool.returnResource(jedis); } /*發布訊息*/ public static void publish(String channel, String message){ Jedis jedis = null ; try{ jedis = jedisPool.getResource(); jedis.publish(channel, message); }catch(Exception e){ System.out.println(e); }finally{ returnResource(jedis); } }; /*訂閱房間*/ public static void subscribe(String[] room, JedisPubSub pubSub){ Jedis jedis = null ; try{ jedis = jedisPool.getResource(); jedis.subscribe(pubSub , room); }catch(Exception e){ System.out.println(e); }finally{ returnResource(jedis); } }}
最後是主函數啟動用戶端了:
public static void main(String[] args) throws InterruptedException { final Client client = new Client(); client.setName("Mark"); final String[] rooms = {"movie::live::room"}; new Thread(new Runnable() { @Override public void run() {// String[] rooms = {"peter::live::room","Bob::live::room"}; client.subscribe(rooms); } }).start(); Thread.sleep(3000); while(true){ System.out.print("say something:"); Scanner scanner = new Scanner(System.in); String message = scanner.nextLine(); if("quit".equals(message)){ break; }else{ client.say(rooms[0], message); System.out.println(); } } String[] unSubRoom ={"movie::live::room"}; client.unSubscribe(unSubRoom); }
到此,一個簡單的聊天室編寫完成。