jive主题的消息有两种显示方式:flat和threaded,具体可以在jive_config.xml中配置,配置的选项是skin.default.threadmode。

当我们使用flat模式的时候,所有的消息将会在主题的根消息下面以时间顺序并且没有缩进地排列显示出来,这种分页显示方式与主题的分页显示方式是类似的。但是,这里的另一种实现方式,即缩进方式,它所有的消息是显示在它自己的父消息(非主题的根消息)之下,并且没有使用分页显示,这种显示方式就是threaded方式,在threaded方式中使用到了一个重要的类TreeWalker。
来看下面的代码(threadMode1.jsp)
TreeWalker treeWalker = thread.treeWalker();
  ForumMessage rootMessage = thread.getRootMessage();
  Iterator messages = treeWalker.recursiveChildren(rootMessage);
这段代码是使用treeWalker获得以rootMessage为树根的所有消息,注意,返回的是一个Iterator,可想而知,在下面的消息显示中,无非是枚举messages里的内容。
下面重点来看一下treeWalker的recursiveChilderen,它是如何递归返回消息的。
首先我们看TreeWalkerProxy里的recursiveChildren.是这样的
public Iterator recursiveChildren(ForumMessage parent) {
        return new IteratorProxy(JiveGlobals.MESSAGE,
                treeWalker.recursiveChildren(parent), authorization, permissions);
   }
它其实是对treeWalker返回的迭代器的一层proxy封装,(这里的treeWalker应该是DbTreeWalder的实例了。再往里看到DbtreeWalker中的方法:
public Iterator recursiveChildren(ForumMessage parent) {
        long [] messages = tree.getRecursiveChildren(parent.getID());
        return new DatabaseObjectIterator(JiveGlobals.MESSAGE, messages,
                parent.getForumThread());
    }
现在到了关键的地方了,tree.getRecursiveChildren(parent.getID()),这个方法直接返回以rootMessage的ID为根的所有的子消息ID号了,前面讲到过DatabaseObjectIterator只是对这些消息ID的一个迭代器封装而已。
稍微解释一下:
tree是二叉树的一个不完全实现,类为LongTree,可以看到系统中有这样一段说明,
*   1
 *   |-- 3
 *   |-- |--4
 *   |-- |--6
 *   |-- 5
 *
 * array index:   0 | 1 | 2 | 3 | 4
 *
 * key:           1 | 3 | 4 | 5 | 6
 * leftChild:     1 | 2 |-1 |-1 |-1
 * rightSiblings    -1 | 3 | 4 |-1 |-1
即系统中使用三个成员数组来描述上面的树,而对于一个主题来说,就存在这样的一棵树,这棵树tree是在treewalker初始化的时候完成的,即:
public DbTreeWalker(DbForumThread thread, DbForumFactory factory) {
        ......
ForumMessage root = thread.getRootMessage();
        int numMessages = thread.getMessageCount(IGNORE_MODERATION_FILTER);
//初始化tree,这时只包含一个根
        tree = new LongTree(root.getID(), numMessages);
Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = ConnectionManager.getConnection();
            pstmt = con.prepareStatement(GET_MESSAGES);
            pstmt.setLong(1, thread.getID());
            ResultSet rs = pstmt.executeQuery();
            while(rs.next()) {
//枚举出数据库中的每个message并加入到数中,由于枚举时按时间升序,所以这个message的parent的id肯定已经在数上了。
                long messageID = rs.getLong(1);
                long parentMessageID = rs.getLong(2);
                tree.addChild(parentMessageID, messageID);
            }
        }
        ......   
}
树在初始化已经形成,现在还是来看核心的部分吧
tree.getRecursiveChildren(parent.getID()),
public long[] getRecursiveChildren(long parentKey) {
//找到根节点的id:startIndex
        char startIndex = findKey(parentKey, (char)1);
//初始化返回的数组,数组的index即是树节点的index。数组的value将是tree的节点的key值,即message的ID值。
        long [] depthKeys = new long[nextIndex-1];
        int cursor = 0;
//得到根节点的左子数
        char siblingIndex = leftChildren[startIndex];
        while (siblingIndex != 0) {
//填充根节点的左子数,即把所有左子数上的节点的key都赋给depthKey.(这是递归)
            cursor = fillDepthKeys(siblingIndex, depthKeys, cursor);
//得到根节点的右子数,继而所有右子数上的节点的key都赋给depthKey
            siblingIndex = rightSiblings[siblingIndex];
        }
        long [] dKeys = new long[cursor];
        for (int i=0; i<cursor; i++) {
            dKeys[i] = depthKeys[i];
        }
        return dKeys;
    }
这段代码,以深度优先算法返回了数的key。

jive论坛消息的threaded显示模式解析相关推荐

  1. 跟我学RocketMQ之批量消息发送源码解析

    上篇文章 跟我学RocketMQ之消息发送源码解析 中,我们已经对普通消息的发送流程进行了详细的解释,但是由于篇幅问题没有展开讲解批量消息的发送.本文中,我们就一起来集中分析一下批量消息的发送是怎样的 ...

  2. Android Handler消息机制不完全解析

    1.Handler的作用 Android开发中,我们经常使用Handler进行页面的更新.例如我们需要在一个下载任务完成后,去更新我们的UI效果,因为AndroidUI操作不是线程安全的,也就意味着我 ...

  3. Android Framework学习(八)之Handler消息机制(Native层)解析

    在深入解析Android中Handler消息机制一文中,我们学习了Handler消息机制的java层代码,这次我们来学习Handler消息机制的native层代码. 在Java层的消息处理机制中,Me ...

  4. android message的作用,Android消息机制之Message解析(面试)

    在android的消息机制中,Message其充当着信息载体的一个角色,通俗的来说,我们看作消息机制就是个工厂的流水线,message就是流水线上的产品,messageQueue就是流水线的传送带.之 ...

  5. 消息系统kafka原理解析

    Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统,后成为Apache的一部分,它使用Scala编写,以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Clouder ...

  6. 消息队列 应用场景 解析

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 另外腾讯云-云社区还有一文不允许转载,但内容挺好的:https://cloud.tencent.co ...

  7. 消息队列应用场景解析

    分布式消息服务DMS是完全托管的高性能消息队列服务,提供普通队列.有序队列.Kafka.RabbitMQ,兼容HTTP.TCP.AMQP协议,为分布式应用提供灵活可靠的异步通信机制.使用DMS,用户可 ...

  8. 队列处理高并发_高并发架构消息队列面试题解析

    面试题 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka.ActiveMQ.RabbitMQ.RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: ...

  9. android 手机内存uri_Android消息机制Handler原理解析

    关注[搜狐技术产品]公众号,第一时间获取技术干货 导读 在Android中,Handler一直是一个热点,在开发过程中,它的使用频率很高,而且在Android源码中Handler都是常客.那么Hand ...

最新文章

  1. CMAKE设置INSTALL工程,分别设置头文件、Lib和DLL的输出路径
  2. oracle 常用命令大汇总
  3. python变量类型-python 变量类型 number
  4. 从Config文件中读取节点的配置信息
  5. tidb mysql5.7_MYSQL5.7实时同步数据到TiDB
  6. android系统优势 研究,Android系统关注度持续保持优势
  7. 极化SAR图像四成分分解
  8. 服务器esn和文件esn不匹配,如何获取服务器ESN
  9. 【团队管理】如何做好技术团队年终复盘
  10. ansible的使用
  11. java未将对象引用设置_未将对象引用设置到对象的实例,怎么解决啊??
  12. 【JDK7】新特性(1) 概述
  13. 开机自动启动 Ubuntu iBus 输入法
  14. Worksoft Certify学习之路
  15. 这样干前端你早该考虑离职了
  16. 极智Paper | 单级特征检测网络 YOLOF
  17. mysql返回第n个值_【单选题】以下MySQL聚合函数,返回n个数值平均值的是( )。 A. MAX B. SUM C...
  18. 用基础jQuery制作个性化留言板
  19. python 超大json文件读取
  20. .net core集成cas统一身份认证

热门文章

  1. 按键精灵脚本转换成c语言,问一个关于按键码转换的问题
  2. bat如何创建多级文件夹
  3. AD2020版本PCB正规拼版操作时,不显示边框的处理办法
  4. 算法:五笔编码,如何根据输入的词条自动生成输入编码
  5. Android app更新模块
  6. Xperia Z2参数及白皮书
  7. 【React】redux和React-redux
  8. c语言静态图片做成动态效果,怎样把图片做成动态图 两张静态图片加过渡效果制作成gif动图...
  9. 为Linux安置红旗紫光输入法
  10. 如何让VeryCD电驴下载完后,自动关机?