原文: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中,代码如下:

  1. public static OfflineMessageStore getInstance() {
  2. return XMPPServer.getInstance().getOfflineMessageStore();
  3. }

我们可以通过getInstance来获得OfflineMessageStore的实例。

如果要向离线表中插入一条数据,那么可以调用addMessage方法,addMessage的源码分析如下:

  1. public void addMessage(Message message) {
  2. // 如果消息为null,直接返回
  3. if (message == null) {
  4. return;
  5. }
  6. // shouldStoreMessage判断哪些消息应该被存储,例如只有类型为chat的消息,才允许被存储。
  7. if(!shouldStoreMessage(message)) {
  8. return;
  9. }
  10.  
  11. JID recipient = message.getTo();
  12. String username = recipient.getNode();
  13. // 如果没有接受者,那么就不必要存离线了。
  14. if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) {
  15. return;
  16. }
  17. else
  18. if (!XMPPServer.getInstance().getServerInfo().getXMPPDomain().equals(recipient.getDomain())) {
  19. // 如果这条消息的域名不对,是发送到其他服务器的,那么也不需要存了
  20. return;
  21. }
  22. // 产生下一条消息的一个序号
  23. long messageID = SequenceManager.nextID(JiveConstants.OFFLINE);
  24.  
  25. // 获得xml格式的消息
  26. String msgXML = message.getElement().asXML();
  27. // 打开数据库连接,并且存储消息到数据库
  28. Connection con = null;
  29. PreparedStatement pstmt = null;
  30. try {
  31. con = DbConnectionManager.getConnection();
  32. pstmt = con.prepareStatement(INSERT_OFFLINE);
  33. pstmt.setString(1, username);
  34. pstmt.setLong(2, messageID);
  35. pstmt.setString(3, StringUtils.dateToMillis(new java.util.Date()));
  36. pstmt.setInt(4, msgXML.length());
  37. pstmt.setString(5, msgXML);
  38. pstmt.executeUpdate();
  39. }
  40.  
  41. catch (Exception e) {
  42. Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
  43. }
  44. finally {
  45. DbConnectionManager.closeConnection(pstmt, con);
  46. }
  47.  
  48. // 为存储离线的用户的缓存空间加上相应的字节数,如果设置了一个用户只能存储几M的数据,那么这个就是统计,这个用户已经存储了多少字节的离线消息
  49. if (sizeCache.containsKey(username)) {
  50. int size = sizeCache.get(username);
  51. size += msgXML.length();
  52. sizeCache.put(username, size);
  53. }
  54. }

如果要删除某条消息,可以使用deleteMessages这个函数,传入用户名作为参数,代码如下:

  1. public void deleteMessages(String username) {
  2. Connection con = null;
  3. PreparedStatement pstmt = null;
  4. try {
  5. // 打开数据库连接
  6. con = DbConnectionManager.getConnection();
  7. // DELETE_OFFLINE为 DELETE FROM ofOffline WHERE username=?
  8. pstmt = con.prepareStatement(DELETE_OFFLINE);
  9. pstmt.setString(1, username);
  10. pstmt.executeUpdate();
  11.  
  12. // 将这个用户已经占用多少字节,重新置为0
  13. removeUsernameFromSizeCache(username);
  14. }
  15. catch (Exception e) {
  16. Log.error("Error deleting offline messages of username: " + username, e);
  17. }
  18. finally {
  19. // 关闭数据库连接
  20. DbConnectionManager.closeConnection(pstmt, con);
  21. }
  22. }

4、小结

 

本节讲解了离线消息的存储类OfflineMessageStore,这个类中有很多关于离线消息的处理函数,需要对openfire离线消息进行扩展的同学,不妨多看看这个类的实现。

Openfire 是怎么存离线消息的更多相关文章

  1. XMPP——Smack[6]离线消息和离线文件的实现

    终篇,三天所学所用,也就这些,如果需要大家要自己去查资料研究研究,功能其实可以很强大的 可惜界面做得不好,一大短处,从大一迄今没整好,主要是个人审美不行,哎 毕业季呀毕业季,明天摆摊卖书,再半月就可能 ...

  2. openfire接收离线消息

    先接收离线消息后再通知openfire上线 //获取离线消息 OfflineMessageManager offlineMessageManager=new OfflineMessageManager ...

  3. xmpp和OpenFire示例,即时聊天室,支持离线消息

    让我说说为什么写这个博客,这是因为我在上周末的研究XMPP和OpenFire,从互联网上下载Demo,但跑不起来.它花了很长的时间.它被改造.抬高.篇博文也是希望后边学习XMPP和OpenFire的同 ...

  4. XMPP——Smack[5]文件传输及离线消息的获取

    三天时间,赶在最后一下午实现了文件的传输,本来需要实现离线文件的发送的,一直没想好怎么弄,找openfire的离线文件插件没找到,后来想出一种方法,起服务器时起了一个系统用户,一直在线,当用户发送离线 ...

  5. Xmpp获取离线消息

    文章只是选取了其中一段,无XMPP基础的人可能看起来有点复杂; 假设我们注册了一个用户,用户名叫shimiso,那么我们如何让shimiso这个用户一登陆就取到离线消息呢? PPConnection. ...

  6. IM消息送达保证机制实现(二):保证离线消息的可靠投递

    1.前言 本文的上篇<IM消息送达保证机制实现(一):保证在线实时消息的可靠投递>中,我们讨论了在线实时消息的投递可以通过应用层的确认.发送方的超时重传.接收方的去重等手段来保证业务层面消 ...

  7. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.2,增加离线消息、离线文件功能(源码)

    (几句题外话:虽然就如何将GG发展为一个有商业价值的产品,我还没有很清晰明确的思路,但是从GG发布以来,通过GG认识了一些朋友,也接了一些小单子,赚了一点小钱.有了一点甜头,目前和2.3个好朋友一起做 ...

  8. Asmack离线消息时间获取

    DelayInformation info = (DelayInformation)message.getExtension("x","jabber:x:delay&qu ...

  9. 离线消息如何实现?-- ESFramework 4.0 快速上手(02)

    在ESFramework 4.0 快速上手一文中,主要介绍了如何使用ESPlus.Rapid命名空间中的引擎来快速地构建基于TCP的网络通信系统,即使是使用ESPlus.Rapid来进行ESFrame ...

随机推荐

  1. 基于clahe的图像去雾

    基于clahe的图像去雾     通过阅读一些资料,我了解到clahe算法对图像去雾有所价值,正好opencv中有了实现,拿过来看一看.   但是现在实现的效果还是有所差异 #);    clahe] ...

  2. Android HandlerThread 完全解析

    HandlerThread本质上是一个线程类,它继承了Thread: HandlerThread有自己的内部Looper对象,可以进行looper循环: 通过获取HandlerThread的loope ...

  3. 基于busybox和LFS的linux系统定制

    自从在大学知道了Linux这玩意是可以定制的之后,一直想做出一版属于自己的Linux系统.最近工作比较闲,终于塌下心来好好学习了一下.   目前来说,我接触的定制Linux的方法主要有两种:   1. ...

  4. 初试 uTenux

    申请的的开发套件到目前还没到手,看到网友们都开始动手干了,我也是按捺不住了,所以就先在悠龙公司的主页下载了uTenux_V1.5.00r160.zip,打算看看,先了解一下. 下面是文件目录表: └─ ...

  5. Java_JDK_HashMap

    (二)HashMap 需要注意的无非几点: 是什么结构,如何存储的? 如何加入元素?既然是hashMap,那么是如何计算hashcode的呢?遇到冲突又是如何解决的呢? 如何删除元素? 当容量不够时是 ...

  6. spring加载hibernate映射文件的几种方式 (转)

    在Spring的applicationContext.xml中配置映射文件,通常是在<sessionFactory>这个 Bean实例中进行的,若配置的映射文件较少时,可以用session ...

  7. CUBRID学习笔记 40 使用net修改数据

    修改 connection.Open();     string queryString = "UPDATE nation set capital = 'X' where `code` = ...

  8. 函数(def)

    一.为什么要使用函数: 面向过程的编程在代码里有很多代码是可以重复利用的,如果使用面向过程编程会使代码显得纷繁复杂,不利于他人和自己日后的阅读.而在函数式编程里,则可以把每个可重复利用的功能封装在一个 ...

  9. install Matlab2016b on Ubuntu 14.04

    From Download Download the install file from Download MATLAB, Simulink, Stateflow, and Other MathWor ...

  10. 1----lua的环境搭建

    本人使用的是LDT用来学习lua,原因是因为本人熟悉Eclipse的操作,并且安装方便 首先需要下载并配置JDK,也就是java的运行环境(以下为官网网址) http://www.oracle.com ...