openfire插件最佳实践(二)基于IQHandler 的Smack+openfire插件

registerUser:使用新的 IQ 注册访客电子邮件的 OpenFire 插件 注册用户 描述 这是 Openfire XMPP 服务器的插件,用于使用 IQ 注册访问者用户的电子邮件。 想要将其电子邮件注册到 XMPP 服务器的访问者应发送 IQ 查询: < iq type = ' set ' xss=removed> < query xss=removed> < email>"email address"</ email> < nick>"nickname"</ nick> </ query> </ iq> 成功后,将发出以下响应: < iq xss=removed xss=removed xss=removed> < query xmlns 立即下载

简单插件开发已经讲解了简单的openfire插件怎样制作,本篇将会讲解如何实现一个简单的和客户端交互的插件。

首先我们要知道,openfire 的四种常用的插件集成方式:

(1)Component:可以接收一个特定子域(sub-domain)的所有包。比如test_componet.hoo.com。所以一个发送给jojo@test_componet.hoo.com的包将被转发给这个componet.

(2)IQHandler:相应包中特定的元素名或命名空间。下面的代码展示了如何注册一个IQHandler.

IQHandlermyHandler = new MyIQHander();

IQRouteriqRouter = XMPPServer.getInstance().getIQRouter();

iqRouter.addHandler(myHandler);

(3)PacketInterceptor:这种方式可以接收系统传输的所有包,并可以随意的丢弃它们。例如,一个interceptor可以拦截并丢弃所有含有不健康信息的消息,或者将它们报告给系统管理员。

(4)使用JiveGlobals.getProperty(String)和 JiveGlobals.setProperty(String, String)方法将我们的插件设置为openfire的一个全局属性。通过实现org.jivesoftware.util.PropertyEventListener方法可以将我们的插件做成一个属性监听器监听任何属性的变化。通过PropertyEventDispatcher.addListener(PropertyEventListener)方法可以注册监听。要注意的一点是,一定要在destroyPlugin()方法中将注册的监听注销。

 

本篇文章将会主要使用IQHandler来实现openfire插件,有关使用PacketInterceptor实现可以参考文章:

http://www.cnblogs.com/hoojo/archive/2013/03/29/2988437.html

 

(一)确定客户端和服务器端进行通讯的IQ的样式

iq类型有四种:get、set、error、result。

这里我们主要讨论get类型,其余类型的处理方式类似。

我们设计的客户端请求格式如下:

<iq id="H40yo-4" type="get"from="test@yourhost/Smack">

<username>111</username>

<query xmlns="hoo.iq.userinfo">

</query>

</iq>

服务器端返回格式如下:

<iq type="result" id="VKe0a-4"to="test@yourhost/Smack">

<query xmlns="hoo.iq.userinfos">

<username>111</username>

</query>

</iq>

(二)编写继承IQHandler的类,用于拦截来自客户端的IQ请求:

[java] view plaincopy

1.  package com.hoo.server.plugin;  

2.    

3.  import org.dom4j.DocumentHelper;  

4.  import org.dom4j.Element;    

5.  import org.dom4j.QName;  

6.  import org.jivesoftware.openfire.IQHandlerInfo;    

7.  import org.jivesoftware.openfire.XMPPServer;  

8.  import org.jivesoftware.openfire.auth.UnauthorizedException;    

9.  import org.jivesoftware.openfire.handler.IQHandler;    

10. import org.jivesoftware.openfire.session.ClientSession;  

11. import org.slf4j.Logger;  

12. import org.slf4j.LoggerFactory;  

13. import org.xmpp.packet.IQ;   

14. import org.xmpp.packet.PacketError;  

15.   

16. import com.hoo.server.plugin.entity.UserInfo;  

17. public class UserInfoIQHander extends IQHandler{  

18.     private static final Logger Log = LoggerFactory.getLogger(UserInfoIQHander.class);  

19.     private IQHandlerInfo info;   

20.     @Override  

21.     public void initialize(XMPPServer server) {  

22.         super.initialize(server);  

23.         dbUserInfoManager = DbUserInfoManager.getInstance();  

24.     }  

25.     public UserInfoIQHander() {    

26.         super("user info");    

27.         info = new IQHandlerInfo("query", "hoo.iq.userinfo");  //这里和我们自定义的iq格式域相同  

28.     }    

29.     

30.     @Override    

31.     public IQHandlerInfo getInfo() {    

32.         return info;    

33.     }    

34.     

35.     @Override    

36.     public IQ handleIQ(IQ packet) throws UnauthorizedException {   

37.         System.out.println(packet.toXML());  

38.         IQ reply = null;  

[java] view plaincopy

1.   reply = IQ.createResultIQ(packet);//根据packet创建一个翻译iq</pre> try { ClientSession session = sessionManager.getSession(packet.getFrom()); if (session == null) { Log.error("Error  

2.   during userInfo. Session not found in " + sessionManager.getPreAuthenticatedKeys() + " for key " + packet.getFrom()); // This error packet will probably won't make it through

3.   reply.setChildElement(packet.getChildElement().createCopy()); 

4.  reply.setError(PacketError.Condition.internal_server_error);  

5.   return reply; } if (IQ.Type.get.equals(packet.getType())) { //获取数据 

6.  Element iq = packet.getElement(); //获取packet中的iq段 

7.  Element query = iq.element("query"); //从iq段中获取query段

8.   Element username = query.element("username");

9.   String userNameStr = null; if(username!=null){  

10.  userNameStr = username.getText();//获取username段中的文字

11.  }else{ //没有传给我username reply.setChildElement(packet.getChildElement().createCopy()); 

12. reply.setError(PacketError.Condition.item_not_found);//为返回数据中填充错误信息 

13. return reply;

14.  } //在安卓端需要配置ProviderManager对数据进行解析 Element  

15.  probeResult = DocumentHelper.createElement(QName.get("query", "hoo.iq.userinfo")) ; probeResult.addElement("username").setText("返回的username");return reply; }} catch (Exception e) {Log.error(e.getMessage(), e);  

16. reply.setChildElement(packet.getChildElement().createCopy());  

17. reply.setError(PacketError.Condition.internal_server_error);//远程服务器错误,客户端无法明确知道发生了什么,客户端也无需知道发生了什么。  

18. return reply;} 

19. return reply

20. } }

(三)在自定义的plugin中注册自定义IQHandler,只要在你的plugin类的initializePlugin方法中添加如下语句: 

21.  server.getIQRouter().addHandler(new UserInfoIQHander());   

这样在开启服务后,openfire就会自动监听hoo.iq.userinfo域的iq query请求。 

服务器端的编译和打包见上一篇文章。

(四)在客户端添加对hoo.iq.userinfo返回的数据的解析,首先自定义一个iq。

22. //自定义一个iq,用于接收和发送自定义iq</pre><pre code_snippet_id="134255" snippet_file_name="blog_20131230_5_2676678" name="code" class="java" style="color: rgb(51, 51, 51); font-size: 13px; line-height: 19px;">public class UserInfo extends IQ{  

23. private String username;  

24.   

25.   

26.     public String getElementName() {    

27.         return "query";    

28.     }    

29.     

30.     public String getNamespace() {    

31.         return "hoo.iq.userinfo";    

32.     }    

33.     

34.     public String getBody() {    

35.     StringBuilder sb = new StringBuilder();   

36.     if(null!=username){  

37.    sb.append("<username>").append(username).append("</username>");  

38.    }  

39.         return sb.toString();    

40.     }    

41. public String getUsername() {  

42. return username;  

43. }  

44.   

45.   

46. public void setUsername(String username) {  

47. this.username = username;  

48. }  

49.   

@Override    

50.     public String getChildElementXML() {    

51.         StringBuilder sb = new StringBuilder();    

52.         sb.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">").append(getBody()).append("</").append(getElementName()).append(">");    

53.         return sb.toString();    

54.     }    

55. }  

  

然后编写对服务器端传输来的数据进行解析的IQProvider  

56. import java.io.ByteArrayInputStream;  

57. import java.io.IOException;  

58.   

59. import javax.xml.parsers.DocumentBuilder;  

60. import javax.xml.parsers.DocumentBuilderFactory;  

61.   

62. import org.jivesoftware.smack.packet.IQ;  

63. import org.jivesoftware.smack.provider.IQProvider;  

64. import org.jivesoftware.smack.util.StringUtils;  

65. import org.w3c.dom.Document;  

66. import org.w3c.dom.Element;  

67. import org.w3c.dom.Node;  

68. import org.w3c.dom.NodeList;  

69. import org.xmlpull.v1.XmlPullParser;  

70. import org.xmlpull.v1.XmlPullParserException;  

71.   

72. import android.util.Log;  

73.   

74.   

75.   

76. public class UserInfoProvider implements IQProvider{  

77.   

78.     private static final String PREFERRED_ENCODING = "UTF-8";  

79.   

80. /***通过这个方法我们可以获取从服务器传来iq**/  

81.     public IQ parseIQ(XmlPullParser parser) throws Exception {  

82.         final StringBuilder sb = new StringBuilder();  

83.         try {  

84.             int event = parser.getEventType();  

85.             // get the content  

86.             while (true) {  

87.                 switch (event) {  

88.                     case XmlPullParser.TEXT:  

89.                         // We must re-escape the xml so that the DOM won't throw an exception  

90.                         sb.append(StringUtils.escapeForXML(parser.getText()));  

91.                         break;  

92.                     case XmlPullParser.START_TAG:  

93.                         sb.append('<').append(parser.getName()).append('>');  

94.                         break;  

95.                     case XmlPullParser.END_TAG:  

96.                         sb.append("</").append(parser.getName()).append('>');  

97.                         break;  

98.                     default:  

99.                 }  

100.      

101.                    if (event == XmlPullParser.END_TAG && "query".equals(parser.getName())) break;  

102.      

103.                    event = parser.next();  

104.                }  

105.            }  

106.            catch (XmlPullParserException e) {  

107.                e.printStackTrace();  

108.            }  

109.            catch (IOException e) {  

110.                e.printStackTrace();  

111.            }  

112.      

113.            String xmlText = sb.toString();  

114.            return new UserInfo();  

115.        }  

116.    }  

最后将IQProvider 在客户端注册下:在connect 时进行注册  

117.    ProviderManager.getInstance().addIQProvider("query", "hoo.iq.userinfo", new UserInfoProvider());

 

(五)测试 

 

118.    在客户端拼接请求:  

119.    UserInfo b = newUserInfo ();  

120.    b.setUsername("111");

121.    b.setType(IQ.Type.GET);  

122.    PacketFilter filter = new AndFilter(new PacketIDFilter(  

123.    b.getPacketID()), new PacketTypeFilter(IQ.class));  

124.    PacketCollector collector = connection.createPacketCollector(filter);  

125.    connection.sendPacket(b);  

126.    UserInfo re = (UserInfo) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());

127.    collector.cancel();// 停止请求results(是否成功的结果)System.out.println(re.toXML());


别让IO口保护二极管坑了你!实测讲解单片机电流倒灌的三种典型症状与防护 本文深入解析单片机电流倒灌的三大典型症状与防护方案,重点分析STM32等单片机在ADC采样异常、系统假死和通信速率异常中的表现。通过实测数据和电路设计建议,提供从基础二极管隔离到专业隔离器件的分级防护策略,帮助工程师有效预防和解决电流倒灌问题。 阅读详情

相关推荐

HTML入门(详细教程),前端入门从这里开始

HTML基础教程,网页框架搭建,表单制作,了解HTML标签的基本用法,每个标签具备哪些属性。

wandertp的博客 1285

【openfire,smack使用总结】--openfire插件开发

1.源码的配置 到https://github.com/igniterealtime/Openfire/releases去下载openfire的源码,导入eclipse,openfire需要Ant工具进行编译,所以还要装上Ant。 2.插件目录结构 装好后,在eclipse的openfire源码目录的plugins目录下创建一个插件文件结构,文件结构见下图,注意图中圈起来的地方。Random

luoyesiqiu的专栏 2597

ADS2023仿真变容二极管特性

仿真S-Param仿真控件,设置为Single Point,将频率设置为1MHz,同时勾选Z-parameters,取消S-parameters,从元件库中选择元器件搭建原理图,并根据器件spice提供的相关参数,对原理图中器件参数进行修改,修改完成的电路图如下图所示。添加var控件和MeasEqn控件,相关设置如图所示,Ct为变容管的电容值,Q0为其品质因数。因此,对变容二极管的模型仿真结果是可以信赖的。将其解压,在spice文件夹中,可以找到我们想要的器件参数,和仿真简要电路图。

weixin_45811090的博客 1万+

Openfire + Smack linux下基本环境搭建和测试

Openfire Install ------------------ xiaoyang @2012-4-13 环境:fedora16,linux3.2内核,mysql服务器 (1)openfire安装 默认安装在/opt/openfire目录下面。 xiaoyang@xiaoyang openfire$ sudo rpm -ivh openfire-3.7.1-1.i386.

jinyeweiyang的专栏 577

HTTPS接口测试翻车实录:为什么浏览器能访问而curl报证书错误?

本文深入分析了HTTPS接口测试中浏览器访问正常而curl报证书错误的典型问题。通过对比浏览器、Postman和curl的工具行为差异,结合Nginx日志与Wireshark抓包,揭示了问题根源在于网络架构中HTTPS请求被意外“降级”为HTTP传输,导致SSL握手失败。文章重点探讨了curl工具严格验证机制暴露的`Peer's Certificate issuer is not recognized`错误,并提供了网络配置修正方案与标准化测试流程。

u9v0w的博客 279

基因家族Motif 分析

MEME

hgz2020的博客 6321

openfire常见问题解决

1.新手在部署openfire源码第一次运行时,大多都会碰到如下异常: Failed to load admin-sidebar.xml file from Openfire classes - admin console will not work correctly. java.lang.NullPointerException at org.jivesoftware.admin.A

qing101hua的专栏 1709

全国(山东、安徽)职业技能大赛--信息安全管理与评估大赛题目+答案讲解——windows应急响应篇

保护数据,捍卫安全,展现技能,赢得荣耀!全国职业技能大赛-信息安全与评估大赛,挑战你的技术,揭示黑客的秘密!加入我们,成为信息安全的守护者!

人若无名,便可专心练剑 908

【openfire插件开发】IQHandler处理IQ请求包(模板方法模式)

原文链接:http://www.hechunchen.info/?p=15 我们知道openfire插件开发主要有3种方式注册方式:1)IQHandler(IQ handlers respond to IQ packets with a particular element name and namespace),2)Interceptor(PacketIntercepto...

weixin_30906425的博客 328

优化YOLOv8检测精度:Damo-YOLO的RepGFPN特征融合技术解析【YOLOv8】

YOLOv8在结构上依旧延续了自YOLOv4以来的CSPNet(Cross Stage Partial Network)和FPN(Feature Pyramid Network)的设计,结合了PANet(Path Aggregation Network)来增强特征的多尺度表达。然而,随着目标检测任务的复杂性增加,如何更有效地融合不同层级的特征成为提升检测性能的关键。Damo-YOLO中的RepGFPN引入了重参数化的思想,通过在训练和推理阶段对特征融合模块进行结构优化,显著提升了检测效果。

博客 1583

Lasso的原理及其与其他特征选择方法的比较进行阐述,然后讨论Lasso优点、缺点以及应用场景,最后给出了代码实例

在机器学习领域中,特征选择(feature selection)是指在模型训练前对数据集进行分析,选择其中有助于预测目标变量或影响模型性能的特征,去除不相关或冗余的特征,提升模型的泛化能力。而Lasso回归是一种很流行的用于特征选择的方法之一。Lasso回归(又称LASSO,least absolute shrinkage and selection operator)是一种线性模型中的特征选择方法。

AI天才研究院 3052

openfire+smack4.2.3

openfire+smack4.2.3 https://blog.youkuaiyun.com/qq_36020545/article/details/80802300 在学习openfire中 其中openfire向我们这种初学者最好不要更改底层代码和进行增加自己的插件,在刚开始学习的过程中可以下了解 xmpp协议 我这边使用java实现smack 和openfire 的联动,再和spark进行联调...

王人冉的博客 798

Simulink仿真模块 -Scope

如果您将 Scope 模块放在具有锁定链接的库或者锁定的库中,当尝试打开示波器窗口时,Simulink 会显示错误。要显示某个库模块中的内部数据,请为库模块添加一个输出端口,然后将此端口连接到您模型中的 Scope 模块。当您在示波器内可视化多个基于帧的信号时,部分帧大小为 1 的信号采样可能不会显示。当在示波器内可视化多个基于帧的信号时,部分帧大小为 1 的信号采样可能不会显示。如果在仿真开始时波形视图关闭,则当在仿真后打开波形视图时,波形视图将显示附加的输入信号的仿真结果。

jk_101的博客 3792

基于XMPP协议IM开发——Openfire 插件开发

这篇文章拖了很久了,呵呵,真是千呼万唤始出来呀。Openfire 服务器端是支持插件开发的,开发过程可能会涉及到数据库的操作,本篇文章专注于Openfire 插件的部分,对服务器端涉及到数据库的开发只做简单介绍。Openfire 是一个用Java 实现的XMPP 服务器,客户端可以通过IQ 的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack 库提供的各种功能来完成的

gc1108960的专栏 1961

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

即时通讯软件openfire+spark+smack

所以我基本上分为三篇文章来介绍此类软件的开发: 第一篇是关于XMPP 协议是啥,IM 是啥以及一个比较有名的开源实现,该开源实现包括三个部分(Spark、Smack和Openfire); 第二篇讲如何开发基于Spark 的客户端IM 插件部分; 第三篇讲如何开发基于Openfire 服务器端的插件部分。 好了,进入正题吧。   什么是XMPP? Extensible Messagin

xiangzhihong8的专栏 1873

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

openfire的服务器插件开发的一个网…

开发你自己的XMPP IM 续 - Openfire 插件开发 - [J2EE] 原文地址~ 继续上一篇的内容,本篇文章介绍开发Openfire 的插件 这篇文章拖了很久了,呵呵,真是千呼万唤始出来呀。Openfire 服务器端是支持插件开发的,开发过程可能会涉及到数据库的操作,本篇文章专注于Openfire 插件的部分,对服务器端涉及到数据库的开发只做简单介绍。 Openfire 是一个用J

忙碌不会钓鱼的专栏 536

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

转:开发你自己的XMPP IM 续 - Openfire 插件开发

继续上一篇的内容,本篇文章介绍开发Openfire 的插件<br /><br />这篇文章拖了很久了,呵呵,真是千呼万唤始出来呀。Openfire 服务器端是支持插件开发的,开发过程可能会涉及到数据库的操作,本篇文章专注于Openfire 插件的部分,对服务器端涉及到数据库的开发只做简单介绍。<br /><br />Openfire 是一个用Java 实现的XMPP 服务器,客户端可以通过IQ 的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack 库提供的各种功能来完成的。其实

YH555的专栏 818

即时通信软件spark+openfire+smack

第一篇是关于XMPP 协议是啥,IM 是啥以及一个比较有名的开源实现,该开源实现包括三个部分(Spark、Smack和Openfire); 第二篇讲如何开发基于Spark 的客户端IM 插件部分; 第三篇讲如何开发基于Openfire 服务器端的插件部分。 好了,进入正题吧。   什么是XMPP? Extensible Messaging and Presence

cluzax的专栏 760

openfire插件开发

XUtils专栏 148

Android openfire插件开发

我这里做了一个例子主要是针对于XMPP的通信。后边会说一点smack和openfire通信的实现。  注:这里的例子中的注释纯属个人理解。  在openfire的源码里有很多插件。我这里实际就是拷贝了其中的一个插件。重名了一下名字。目录结构如下:   貌似图片传不上来了。如果看不到图,就看看源码中的其他插件的例子。跟其他插件的目录结构是一样一样的。 在这些文件里最重要的就是plugin....

weixin_34161083的博客 157
上一篇: openfire插件最佳实践(一)简单插件开发
下一篇: openfire插件最佳实践(三) 用户加入指定群组功能
ldwtill
博客等级 码龄18年 49粉丝 84原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值