• 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_srcsrcjavaorgjivesoftwareopenfire下,有一个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离线消息进行扩展的同学,不妨多看看这个类的实现。

  • 相关阅读:
    Winform 的一个多线程绑定DataGrid数据源的例子
    General Database Adapter for Biztalk Server 2006 介绍
    Developing a Transactional Biztalk adapter
    整理了一些DataGrid ColumnStyle
    Biztalk 调用带Soap Head WebService的方法
    提问:如何控制控制台程序的输入/输出焦点的位置
    Biztalk 2006 adapter的开发比2004容易的多
    数据库同步设计方案
    解决Microsoft Visual Studio Code Name "Orcas" 不能安装的问题
    C# 退出提示 事件提示两次问题
  • 原文地址:https://www.cnblogs.com/shihaiming/p/6213878.html
Copyright © 2020-2023  润新知