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 ...
随机推荐
- Ajax案例:简易的购书网页
****使用Ajax可以不需要刷新整个页面,而使局部页面更新的技术: ****JSON是JavaScript得原生格式,JavaScript中处理JSON数据不需要特殊的工具或架包,其规则很简单,对象 ...
- jsp:和属性相关的方法,请求的转发,重定向
jsp中与属性相关的方法: 方法: void setAttribute(String name, Object o): 设置属性 Object getAttribute(String name):获取 ...
- nylg 640 Geometric Sum
Geometric Sum 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 Compute (a + a^2 + … + a^n) mod m.(a+a2+…an)m ...
- Android 4.4之后删除短信进行处理
android 4.4删除短信 android 4.4之后非默认的短信应用已经没有办法删除短信了.像以前那样用如下方法是不会没法删除短信的(即使在xml中配置了短信的读写权限),同时也不会有报错或其他 ...
- swift + jj实践
1,UIButton里面的字体和图片左对齐 button.imageEdgeInsets = UIEdgeInsetsMake(0,180/2,0.0,320/2) let btnRect = but ...
- C#获取当前日期时间(转)
我们可以通过使用DataTime这个类来获取当前的时间.通过调用类中的各种方法我们可以获取不同的时间:如:日期(2008-09-04).时间(12:12:12).日期+时间(2008-09-04 12 ...
- ProgressDialog 的 使用
一 . ProgressDialog ProgressDialog是AlertDialog类的一个扩展,可以为一个未定义进度的任务显示一个旋转轮形状的进度动画,或者为一个指定进度的任务显示一个进度条. ...
- UVA 1291 十四 Dance Dance Revolution
Dance Dance Revolution Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Su ...
- jquery ajax请求时,设置请求头信息
设置一个名为 headers 的参数 参考代码: // attempt to make an XMLHttpRequest to indeed.com // jQuery 1.6.1 and Chro ...
- [HDOJ4609]3-idiots(FFT,计数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:n个数,问取三个数可以构成三角形的组合数. FFT预处理出两个数的组合情况,然后枚举第三个 ...