这一篇紧接着上面继续了。
方案二
基于redis的消息回执。主要流程分为下面几个步骤:
1)将消息暂存储与redis中,设置好消息的过期时间
2)客户端回执消息id来消灭暂存的消息
3)开通单独线程论坛在第1)步中的消息。根据消息的时间重新发送消息。如果消息第一次存放的时间大雨有效期(自定义10秒),解析消息中的to查找用户是否还在线。如果在则T掉(因为它长时间不理会服务的重要命令),如果不在线则将消息放置离线表。
OK,先来看看消息的存储格式吧。
1.MESSAGE消息 用户集合
SADD SOGU:[username] [VALUE(messageID)] [VALUE(messageID)] ...
2.已读消息设备集合
SADD RT:[terminalid] [VALUE(messageID)] [VALUE(messageID)] ...
3.消息内容
HMSET OGM:[messageID] CREATIONDATE [VALUE] UPDATEDATE [VALUE] STANZA [VALUE]
4.用户、设备关联
SADD URT:[USERNAME] [VALUE(terminalid)] .......
(先根据消息id查找时间,在java中排序后 查找stanza)
MESSAGE
--离线表
ZADD OFOFFLINE:[username] [INDEX(时间戳)] [VALUE(messageID)] 、[VALUE]、[VALUE]...... [VALUE]
HMSET OFOFFLINE:[messageID] STANZA[VALUE]
CREATIONDATE [VALUE] MESSAGESIZ[VALUE]
将消息暂时消息存储:
public void storeMessage(String username, Packet packet) {
Jedis jedis = XMPPServer.getInstance().getGroupRedisManager().getJedis();
String packetID = "";
if (packet instanceof Message)
packetID = ((Message)packet).getID();
else if (packet instanceof IQ)
packetID = ((IQ)packet).getID();
else
return;
try {
jedis.sadd("SOGU:" + username, packetID);
Map<String, String> hash = new HashMap<String, String>();
hash.put("STANZA", packet.toXML());
hash.put("CREATIONDATE", StringUtils.dateToMillis(new Date()));
jedis.hmset("OGM:" + packetID, hash);
} finally {
XMPPServer.getInstance().getGroupRedisManager().returnRes(jedis);
}
htp.execute(addMessagesToDB(packet));
}
private Runnable addMessagesToDB(final Packet packet) {
return new Runnable() {
@Override
public void run() {
MyDBopt.insertMessage(packet);
}
客户端收到消息来回执服务端的操作
private void handle(IQ packet) {
JID recipientJID = packet.getTo();
if (IQ.Type.crs != packet.getType()) {
// Check if the packet was sent to the server hostname
if (recipientJID != null &