您的位置:首页 > 数据库 > Redis

基于订阅/发布模式的简易聊天室实现(java+redis)

2016-03-23 15:55 936 查看
对于本篇博文主要从以下两部分介绍简易聊天室的实现:

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);
}


到此,一个简单的聊天室编写完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java redis 发布 聊天