基於訂閱/發布模式的簡易聊天室實現(java+redis)

來源:互聯網
上載者:User

對於本篇博文主要從以下兩部分介紹簡易聊天室的實現:
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);    }

到此,一個簡單的聊天室編寫完成。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.