Openfire 是怎么存离线消息
原文:http://myopenfire.com/article/getarticle/26
1、openfire默认怎么存离线消息
在默认情况下,不添加任何插件的情况下,当用户不在线,对于发送给该用户的消息,会被openfire存放到数据库中的ofoffline表中。
为了更深入的了解离线消息的原理,我们来看一下ofoffline这个表,这个表的结构如下所示:
下面对这几个字段进行详细说明:
(1)Username:是用户名,如myopenfire1、myopenfire2。
(2)MessageID:是openfire产生的一个数字,openfire每处理一条消息到离线,这个值就会增1。
(3)CreateDate:表示这条消息被插入数据库的时间,注意插入数据库的时间不一定是这条消息到达服务器的时间。因为他们之间始终是有一点误差的。
(4)MessageSize:表示存储在stanza字段中的消息的字节数。
(5)Stanza:翻译为节的意思,这里指的就是数据包,存放的是message消息。
2、离线表中实际的数据是什么
Ok,我们来看看实际的存储,你就会更容易理解了,如下图是离线表中的数据:
注意stanza是存放的是xmpp协议表示的消息。
3、存放离线消息的类
在目录openfire_src\src\java\org\jivesoftware\openfire下,有一个OfflineMessageStore.java类,这个类就是用来存放离线消息的。
首先这个类是一个单例类,它的实例保存在XMPPServer中,代码如下:
public static OfflineMessageStore getInstance() {
return XMPPServer.getInstance().getOfflineMessageStore();
}
我们可以通过getInstance来获得OfflineMessageStore的实例。
如果要向离线表中插入一条数据,那么可以调用addMessage方法,addMessage的源码分析如下:
public void addMessage(Message message) {
// 如果消息为null,直接返回
if (message == null) {
return;
}
// shouldStoreMessage判断哪些消息应该被存储,例如只有类型为chat的消息,才允许被存储。
if(!shouldStoreMessage(message)) {
return;
}
JID recipient = message.getTo();
String username = recipient.getNode();
// 如果没有接受者,那么就不必要存离线了。
if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) {
return;
}
else
if (!XMPPServer.getInstance().getServerInfo().getXMPPDomain().equals(recipient.getDomain())) {
// 如果这条消息的域名不对,是发送到其他服务器的,那么也不需要存了
return;
}
// 产生下一条消息的一个序号
long messageID = SequenceManager.nextID(JiveConstants.OFFLINE);
// 获得xml格式的消息
String msgXML = message.getElement().asXML();
// 打开数据库连接,并且存储消息到数据库
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_OFFLINE);
pstmt.setString(1, username);
pstmt.setLong(2, messageID);
pstmt.setString(3, StringUtils.dateToMillis(new java.util.Date()));
pstmt.setInt(4, msgXML.length());
pstmt.setString(5, msgXML);
pstmt.executeUpdate();
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
// 为存储离线的用户的缓存空间加上相应的字节数,如果设置了一个用户只能存储几M的数据,那么这个就是统计,这个用户已经存储了多少字节的离线消息
if (sizeCache.containsKey(username)) {
int size = sizeCache.get(username);
size += msgXML.length();
sizeCache.put(username, size);
}
}
如果要删除某条消息,可以使用deleteMessages这个函数,传入用户名作为参数,代码如下:
public void deleteMessages(String username) {
Connection con = null;
PreparedStatement pstmt = null;
try {
// 打开数据库连接
con = DbConnectionManager.getConnection();
// DELETE_OFFLINE为 DELETE FROM ofOffline WHERE username=?
pstmt = con.prepareStatement(DELETE_OFFLINE);
pstmt.setString(1, username);
pstmt.executeUpdate();
// 将这个用户已经占用多少字节,重新置为0
removeUsernameFromSizeCache(username);
}
catch (Exception e) {
Log.error("Error deleting offline messages of username: " + username, e);
}
finally {
// 关闭数据库连接
DbConnectionManager.closeConnection(pstmt, con);
}
}
4、小结
本节讲解了离线消息的存储类OfflineMessageStore,这个类中有很多关于离线消息的处理函数,需要对openfire离线消息进行扩展的同学,不妨多看看这个类的实现。
Openfire 是怎么存离线消息的更多相关文章
- XMPP——Smack[6]离线消息和离线文件的实现
终篇,三天所学所用,也就这些,如果需要大家要自己去查资料研究研究,功能其实可以很强大的 可惜界面做得不好,一大短处,从大一迄今没整好,主要是个人审美不行,哎 毕业季呀毕业季,明天摆摊卖书,再半月就可能 ...
- openfire接收离线消息
先接收离线消息后再通知openfire上线 //获取离线消息 OfflineMessageManager offlineMessageManager=new OfflineMessageManager ...
- xmpp和OpenFire示例,即时聊天室,支持离线消息
让我说说为什么写这个博客,这是因为我在上周末的研究XMPP和OpenFire,从互联网上下载Demo,但跑不起来.它花了很长的时间.它被改造.抬高.篇博文也是希望后边学习XMPP和OpenFire的同 ...
- XMPP——Smack[5]文件传输及离线消息的获取
三天时间,赶在最后一下午实现了文件的传输,本来需要实现离线文件的发送的,一直没想好怎么弄,找openfire的离线文件插件没找到,后来想出一种方法,起服务器时起了一个系统用户,一直在线,当用户发送离线 ...
- Xmpp获取离线消息
文章只是选取了其中一段,无XMPP基础的人可能看起来有点复杂; 假设我们注册了一个用户,用户名叫shimiso,那么我们如何让shimiso这个用户一登陆就取到离线消息呢? PPConnection. ...
- IM消息送达保证机制实现(二):保证离线消息的可靠投递
1.前言 本文的上篇<IM消息送达保证机制实现(一):保证在线实时消息的可靠投递>中,我们讨论了在线实时消息的投递可以通过应用层的确认.发送方的超时重传.接收方的去重等手段来保证业务层面消 ...
- 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.2,增加离线消息、离线文件功能(源码)
(几句题外话:虽然就如何将GG发展为一个有商业价值的产品,我还没有很清晰明确的思路,但是从GG发布以来,通过GG认识了一些朋友,也接了一些小单子,赚了一点小钱.有了一点甜头,目前和2.3个好朋友一起做 ...
- Asmack离线消息时间获取
DelayInformation info = (DelayInformation)message.getExtension("x","jabber:x:delay&qu ...
- 离线消息如何实现?-- ESFramework 4.0 快速上手(02)
在ESFramework 4.0 快速上手一文中,主要介绍了如何使用ESPlus.Rapid命名空间中的引擎来快速地构建基于TCP的网络通信系统,即使是使用ESPlus.Rapid来进行ESFrame ...
随机推荐
- IOS中两个view的切换
在ios中,rootview为PassWordViewController,secondview为SecondViewController,实现在rootview中听过一个跳转按钮实现跳转到secon ...
- asp.net c# 打开新页面或页面跳转
1.最常用的页面跳转(原窗口被替代):Response.Redirect("XXX.aspx"); 2.利用url地址打开本地网页或互联网:Respose.Write(" ...
- hdu1016 Prime Ring Problem
dfs,用全局数组和变量保存并更新当前状态. 答案可以直接在搜索结束时打印,n为奇数时方案数为0. acm.hdu.edu.cn/showproblem.php?pid=1016 #include & ...
- Power Strings 分类: POJ 串 2015-07-31 19:05 8人阅读 评论(0) 收藏
Time Limit:3000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ ...
- Labeling Balls 分类: POJ 2015-07-28 19:47 10人阅读 评论(0) 收藏
Labeling Balls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11893 Accepted: 3408 Descr ...
- SharePoint自动化系列——Create a local user and add to SharePoint
转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ 实现过程:在本地创建一个local user并将该user添加到Administrators组中, ...
- 蚂蚁运输(ant)
蚂蚁运输(ant)Time Limit:5000ms Memory Limit:64MB[题目描述] LYK 在观察一些蚂蚁.蚂蚁想要积攒一些货物来过冬.积攒货物的方法是这样的.对于第i只蚂蚁, 它要 ...
- 免费PHP WEB环境套件介绍
PHPNOW--Apache + PHP + MySQL(windows) easyphp--Apache + PHP + MySQL+phpmyadmin(windows) xampp(中文站点)- ...
- MVC api json 格式
输出json var formatters = config.Formatters.Where(formatter => formatter.SupportedMediaTypes.Where( ...
- 11个让你吃惊的 Linux 终端命令
原文:http://linux.about.com/od/commands/tp/11-Linux-Terminal-Commands-That-Will-Rock-Your-World.htm 作者 ...