(转)OpenFire源码学习之七:组(用户群)与花名册(用户好友)
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413651
Group
在openfire中的gorop——组,也可以理解为共享组。什么叫共享组呢。当有一个组名字为“学习组”,当其他用户加入这个组的时候,那么他们会自动成为相互的好友。实际上
在openfire内,用户的好友不仅仅只是花名册,还包括共同在一个组的成员。当然这个组有很多好处。比如,那我们公司做的一个项目为例。我们做学校老师与家里沟通的的APP,需要预先将老师和家长做成好友,这个就不要重新让用户手动去添加了,可以直接生成放在用一个组内。当然,还有很多其他的用户。大家随意发挥吧,呵呵。。。
Group通讯
这里所讲的group通讯主要是将客户端与服务端之间基于group之上的操作通讯。
比如服务端的CRUD操作,如何知会给客户端。目前据本人了解,openfire提供的客户端版本中都没让用户自己操作gruop的功能,我想在客户端也并不需要这些功能。下面几个小节就主要讲讲服务端的操作。
终端查询
客户端发送查询的命令如下:
- <iq id="9Fzzk-5" type="get">
- <sharedgroup xmlns="http://www.jivesoftware.org/protocol/sharedgroup">
- </sharedgroup>
- </iq>
服务端怎么处理呢?
IQSharedGroupHandler,就是在针对客户端的查询命令处理。该类位于org.jivesoftware.openfire.handler下。
源码如下:
- @Override
- public IQ handleIQ(IQ packet) throws UnauthorizedException {
- IQ result = IQ.createResultIQ(packet);
- String username = packet.getFrom().getNode();
- <span style="white-space:pre"> </span>//以下是一些校验。。。 此处省略....
- <span style="white-space:pre"> </span>//这里才开始处理。
- Collection<Group> groups = rosterManager.getSharedGroups(username);
- Element sharedGroups = result.setChildElement("sharedgroup",
- "http://www.jivesoftware.org/protocol/sharedgroup");
- for (Group sharedGroup : groups) {
- String displayName = sharedGroup.getProperties().get("sharedRoster.displayName");
- if (displayName != null) {
- sharedGroups.addElement("group").setText(displayName);
- }
- }
- return result;
- }
从源码中,可以看书,groups集合从用户的花名册中得到。RosterManager。
那么就一起看看源码吧
- public Collection<Group> getSharedGroups(String username) {
- Collection<Group> answer = new HashSet<Group>();
- Collection<Group> groups = GroupManager.getInstance().getSharedGroups(username);
- for (Group group : groups) {
- String showInRoster = group.getProperties().get("sharedRoster.showInRoster");
- if ("onlyGroup".equals(showInRoster)) {
- if (group.isUser(username)) {
- // The user belongs to the group so add the group to the answer
- answer.add(group);
- }
- else {
- // Check if the user belongs to a group that may see this group
- Collection<Group> groupList = parseGroups(group.getProperties().get("sharedRoster.groupList"));
- for (Group groupInList : groupList) {
- if (groupInList.isUser(username)) {
- answer.add(group);
- }
- }
- }
- }
- else if ("everybody".equals(showInRoster)) {
- // Anyone can see this group so add the group to the answer
- answer.add(group);
- }
- }
- return answer;
- }
那么这里比较重要的方法:
Collection<Group> groups =
GroupManager.getInstance().getSharedGroups(username);
这里调用了DAO,首先会从缓存列表中根据用户名获取所拥有的组。如果缓存中不存在则,查询数据库。
缓存Cache<String, Object> groupMetaCache;
那么group设计到了那些表呢。主要有3张表:
ofGroup、ofGroupProp、ofGroupUser
ofGroup该表就是grouo的信息内容:
ofGroupProp是group的权值属性表:
Name是权值名称,propValue是值,在上面源码中看到的onlyGroup、everybody就是值了。比如onlyGroup就是该组只对该组成员有效,everybody则是针对所有成员,所有人都能加入这个组当中去。
ofGroupUser这个是用户与组关系表。里面有三个值
组名+用户+用户所在该组的权限。
关于组的信息就说到这,解下继续源码for里面很简单了,就是封装组。
然后服务端返回客户端组消息,内容如下:
- <iq type="result" id="9Fzzk-5" to="zhangf@8ntmorv1ep4wgcy/Spark 2.6.3#android">
- <sharedgroup xmlns="http://www.jivesoftware.org/protocol/sharedgroup">
- <group>testg </group>
- </sharedgroup>
- </iq>
从这段消息中可以知道,服务返回是以人(用户)为基础单位,告诉客户端,这个用户(也就是你的好友)所跟您在一起的组。本人认为这样并不是很好。个人认为服务端的返回应该是这样:
- <group name=’testgroup’>
- <username>u1</username>
- <username>u2</username>
- ......
- </group>
当然openfire并没有这么做,至少在3.8.1的版本没能这么做。这也为了迎合用户的花名册了。
Ok,查询就都这里。
控制台上的操作
当管理将一个用户添加到group中时:
1、向客户端发送新的iq,告诉它你有新的好友了,你和这个组了的一个人的好友关系是
both(互为好友为什么互为好友呢,之前说过了,凡事群组的成员都是互为好友的,两个用户都加入对方是both,那么可以自动获取到对方的状态,相当于加了监听)。当然
这个组内有多少个成员,便会发送多少条消息。内容如下:
- <iq type="sgo" id="784-19" to="huwf@hytest240/Spark 2.6.3#10000141" from="hytest240">
- <query xmlns="jabber:iq:roster">
- <item jid="10530@hytest240" name="好友名称" subscription="both">
- <group>groupname#groupdesc</group>
- </item>
- </query>
- </iq>
注意<group>groupname#groupdesc</group>这里面有个“#”这个是本人自己加的。因为我们项目中把groupname作为了id,desc则为组的名称。实际上我们没有用到描述这个字段。
2、当管理台删除一个用户的时候,步骤个上面一样。发送的消息内容如下:
- <iq type="sgo" id="812-26" to="huwf@hytest240/Spark 2.6.3#10000141" from="hytest240">
- <query xmlns="jabber:iq:roster">
- <item jid="10015@hytest240" subscription="remove"/>
- </query>
- </iq>
它只是告诉你,你没这个好友了。当然这个消息是删除正在在线状态的用户。删除其他用户的消息,这里就不在啰嗦了。
Group事件
在控制台操作的group出发的事件由GroupManager控制。在GroupManager的构造函数中添加了监听事件。有7个监听事件。
1、groupCreated。创建group
1)添加gourp权值属性
2)加入group缓存
3)删除元缓存
2、groupDeleting 删除group
1)发送iq消息给组内成员“jabber:iq:group:delete”
2)从缓存中移除
3)从db中移除
......
花名册
处理流程
终端获取流程:
1、终端发送
- <iq id="Ho4CO-2" type="get">
- <query xmlns="jabber:iq:roster"></query>
- </iq>
2、系统返回
- <iq type="result" id="Ho4CO-2" to="zhangf@8ntmorv1ep4wgcy/Spark 2.6.3#android">
- <query xmlns="jabber:iq:roster">
- <item jid="guany@8ntmorv1ep4wgcy" name="关羽" subscription="both">
- <group>testg </group>
- </item>
- <item jid="liub@8ntmorv1ep4wgcy" name="liub" subscription="both">
- <group>我的兄弟</group>
- <group>testg </group>
- </item>
- <item jid="zhugl@8ntmorv1ep4wgcy" name="zhugl" subscription="from">
- <group>军机处</group>
- </item>
- </query>
- </iq>
走进源码看IQRosterHandler的处理。IQRosterHandler是服务端对用户花名册的处理。
IQRosterHandler位于org.jivesoftware.openfire.handler。
IQRosterHandler中的handleIQ方法,根据客户端的IQ请求中的to属性判别用户是查询还是删除。
查询:
- if (recipientJID == null || recipientJID.getNode() == null ||
- !UserManager.getInstance().isRegisteredUser(recipientJID.getNode())) {
- returnPacket = manageRoster(roster);
- }
manageRoster方法,有两个判断
1、if (IQ.Type.get == type) 这里从缓存中查找用户好友,并封装消息
2、else if (IQ.Type.set == type)由分为两种
1)removeItem移除列表
2)createRosterItem创建列表
removeRosterItem:删除用户列表。并广播整个列表好友删除消息。
组与花名册就先到这,以后还补充。这块还是比较简单。主要看handle这个包下的类。
(转)OpenFire源码学习之七:组(用户群)与花名册(用户好友)的更多相关文章
- (转)OpenFire源码学习之六:用户注册
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413509 用户注册 注册流程: 1.客户端进行握手给服务端发送连接消息: <s ...
- (转)OpenFire源码学习之二十七:Smack源码解析
转:http://blog.csdn.net/huwenfeng_2011/article/details/43484199 Smack Smack是一个用于和XMPP服务器通信的类库,由此可以实现即 ...
- (转)OpenFire源码学习之十八:IOS离线推送
转:http://blog.csdn.net/huwenfeng_2011/article/details/43458213 IOS离线推送 场景: 如果您有iOS端的APP,在会话聊天的时候,用户登 ...
- (转)OpenFire源码学习之十:连接管理(上)
转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827 关于连接管理分为上下两部分 连接管理 在大并发环境下,连接资源 需要随着用 ...
- (转)OpenFire源码学习之四:openfire的启动流程
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413233 openfire启动 ServerStarter 启动流程图: 启动的总入 ...
- (转)即时通讯IM OpenFire源码学习之三:在Eclipse中构建源码
转:http://blog.csdn.net/huwenfeng_2011/article/details/43412617 源码搭建 下载地址: 地址:http://www.igniterealti ...
- (转)OpenFire源码学习之十三:消息处理
转:http://blog.csdn.net/huwenfeng_2011/article/details/43417817 消息处理流程总揽(该图来源于互联网,图片很大,不过类容还是挺清楚的.不方便 ...
- (转)OpenFire源码学习之八:MUC用户聊天室
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413817 MUC 房间属性设置 以上属性存储在MUCPersistenceManag ...
- (转)OpenFire源码学习之五:用户登录
转:http://blog.csdn.net/huwenfeng_2011/article/details/43413377 登陆 登陆认证,客户端发送认SASL证消息: <auth mecha ...
随机推荐
- paper 135:关于C#泛型的一些讲解
计划着要用一个月的时间把 C#语言Windows程序设计 搞定,现在是零零散散的知识点,日积月累吧!朋友们,看这里咯~呵呵 原文地址:http://www.blogjava.net/Jack2007 ...
- 服务器一般达到多少QPS比较好?
每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量. 原理:每天80%的访问集中在20%的时间里,这20%时 ...
- 2018icpc南京/gym101981 G Pyramid 找规律
题意: 数一个金字塔里面有多少个正三角形. 题解: ans[n]=n*(n-1)*(n-2)*(n-3)/24 #include<bits/stdc++.h> using namespac ...
- Linux下安装Tomcat服务器
Linux下安装Tomcat服务器 一.总结 一句话总结: linux多用才能熟 1.阿里云上面我们买的服务器,怎么让它可以访问特定的端口? 就是给服务器的安全组添加规则:实例-->更多--&g ...
- HTML-参考手册: 画布
ylbtech-HTML-参考手册: 画布 1.返回顶部 1. HTML5 <canvas> 参考手册 描述 HTML5 <canvas> 标签用于绘制图像(通过脚本,通常是 ...
- mybatis plus的条件构造器
我们在使用条件构造器的时候要使用QueryWrapper或者UpdateWrapper来充当条件语句来进行构造 QueryWrapper(LambdaQueryWrapper) 和 UpdateWra ...
- jsonp协议 java服务端、JQuery客户端 简单实现原理
原文链接:https://blog.csdn.net/Activity_Time/article/details/96440806 1. 概述 Jsonp(JSON with Padding) 是 j ...
- 安装graphviz
环境win10 1. 下载安装包首先进入官网下载msi文件 安装,一路next,不需要注意什么 2.设置环境变量 安装完毕之后,我们需要手动配置环境变量. 找到刚才我们安装地址,进入graphviz, ...
- Java8环境设置
假设你已经安装在 C:Program Filesjavajdk 目录: 在“我的电脑”右键单击并选择“属性”. 在“高级”选项卡下单击“环境变量”按钮. 现在,改变“Path”变量,因此,它也包含了路 ...
- JOGL教程
本章介绍了OpenGL,Java OpenGL绑定(GL4java,LWJGL,JOGL)和JOGL比其他的OpenGL的优点. Java支持OpenGL(JOGL)是近期在Java OpenGL图形 ...