OpenFire二次开发环境搭建.docx

上传人:b****8 文档编号:30539950 上传时间:2023-08-16 格式:DOCX 页数:14 大小:357.32KB
下载 相关 举报
OpenFire二次开发环境搭建.docx_第1页
第1页 / 共14页
OpenFire二次开发环境搭建.docx_第2页
第2页 / 共14页
OpenFire二次开发环境搭建.docx_第3页
第3页 / 共14页
OpenFire二次开发环境搭建.docx_第4页
第4页 / 共14页
OpenFire二次开发环境搭建.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

OpenFire二次开发环境搭建.docx

《OpenFire二次开发环境搭建.docx》由会员分享,可在线阅读,更多相关《OpenFire二次开发环境搭建.docx(14页珍藏版)》请在冰豆网上搜索。

OpenFire二次开发环境搭建.docx

OpenFire二次开发环境搭建

1、导入项目

2、ANT运行配置

3、部署项目

4、启动服务器

5、访问服务器

6、代码研究

Openfire的socket网络连接包括:

1.服务器和服务器之间的连接(监听在端口5269)

2.外部组件和服务器之间的连接(监听在端口5275)

3.多元(complex)连接(监听在端口5269)

4.客户端和服务器的连接(监听在端口5222)

5.客户端和服务器通过TLS/SSL3.0的连接。

(监听在端口5223)

客户端和服务器的连接分析:

A、这些连接都是通过ConnectionManager接口实现管理的,程序中对ConnectionManager接口的实现类是org.jivesoftware.openfire.spi.ConnectionManagerImpl,它是作为一个模块(Module)类加载到服务器中的。

在ConnectionManagerImpl中是通过调用startClientListeners方法来初始化和开始端口监听的。

startClientListeners方法使用的是Apache的Mina框架来实现网络连接的,Mina框架的模式如下:

几个接口:

IoAccepter相当于网络应用程序中的服务器端

IoConnector相当于客户端

IoSession当前客户端到服务器端的一个连接实例

IoHandler业务处理逻辑

IoFilter过滤器用于连接通讯层接口与业务层接口

IoFilter:

IoFilter为MINA的功能扩展提供了接口。

它拦截所有的IO事件进行事件的预处理和后处理。

它与Servlet中的filter机制十分相似。

多个IoFilter存放在IoFilterChain中

IoFilter能够实现以下功能:

数据转换

事件日志

性能检测

在Openfire中主要用filter这种机制来进行数据转换。

B、ProtocolCodecFactory:

ProtocolCodecFactory提供了方便的Protocol支持,通过它的Encoder和Decoder,可以方便的扩展并支持各种基于Socket的网络协议,比如HTTP服务器、FTP服务器、Telnet服务器等等。

要实现自己的编码/解码器(codec)只需要实现interface:

ProtocolCodecFactory即可,在Openfire中实现ProtocolCodecFactory的类为org.jivesoftware.openfire.nio.XMPPCodecFactory。

IoHandler:

MINA中,所有的业务逻辑都有实现了IoHandler的class完成,当事件发生时,将触发IoHandler中的方法:

sessionCreated

sessionOpened

sessionClosed

sessionIdle

exceptionCaught

messageReceived

messageSent

C、在Openfire中客户端和服务器连接的IoHandler实现类是org.jivesoftware.openfire.nio.ClientConnectionHandler,它是从ConnectionHandler中继承来的。

D、startClientListeners方法首先为Mina框架设置线程池,再将一个由XMPPCodecFactory作为ProtocolCodecFactory的Filter放入到FilterChain中,然后绑定到端口5222,并将ClientConnectionHandler作为IoHandler对数据进行处理。

完成这些步骤后Openfire就在5222等待客户端的连接。

E、客户端连接的处理过程:

当有客户端进行连接时根据Mina框架的模式首先调用的是sessionOpened方法。

sessionOpened首先为此新连接构造了一个parser(XMLLightWeightParser),这个parser是专门给XMPPDecoder(是XMPPCodecFactory的解码器类)使用的,再创建一个Openfire的Connection类实例connection和一个StanzaHandler的实例。

最后将以上的parser,connection和StanzaHandler的实例存放在Mina的session中,以便以后使用。

当有数据发送过来时,Mina框架会调用messageReceived方法。

messageReceived首先从Mina的session中得到在sessionOpened方法中创建的StanzaHandler实例handler,然后从parsers中得到一个parser(如果parsers中没有可以创建一个新的实例)(注意这个parser和在sessionOpened方法中创建的parser不同,这个parser是用来处理Stanza的,而在sessionOpened方法中创建的parser是在filter中用来解码的,一句话说就是在sessionOpened方法中创建的parser是更低一层的parser)。

最后将xml数据包交给StanzaHander的实例hander进行处理。

F、StanzaHander的实例hander处理xml数据包的过程

StanzaHander首先判断xml数据包的类型,如果数据包以“

stream”打头那么说明客户端刚刚连接,需要初始化通信(符合XMPP协议)Openfire首先为此客户端建立一个与客户端JID相关的ClientSession,而后与客户端交互协商例如是否使用SSL,是否使用压缩等问题。

当协商完成之后进入正常通信阶段,则可以将xml数据包交给这个用户的ClientSession进行派送(deliever),经过派送数据包可以发送给PacketRouteImpl模块进行处理。

7、功能扩展

A、修改源代码

⑴用户的创建。

由于源代码中用户信息不能满足要求,需要扩展。

服务器端创建用户比较简单,主要是客户端的创建比较复杂,

主要有4个步骤,客户端发送创建用户的请求(get请求),请求创建的用户字段,服务器端接收到之后进行过滤,然后返回信息(result),信息中只包含合法的用户属性,客户端收到之后,再将合法的用户字段发送给服务器(set请求),服务器再根据收到的用户字段创建用户,即写入数据库。

⑵用户的查询。

过程类似上面用户的创建。

B、插件开发

Openfire服务器端是支持插件开发的,开发过程可能会涉及到数据库的操作,本篇文章专注于Openfire插件的部分,对服务器端涉及到数据库的开发只做简单介绍。

Openfire是一个用Java实现的XMPP服务器,客户端可以通过IQ的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack库提供的各种功能来完成的。

其实利用插件方式来扩展Openfire服务器端主要有两种扩展方式,一种是对服务器控制台页面进行扩展(不是本文的主要内容),其实就是遵循Openfire页面的布局方式,进行相应的页面扩展和功能扩展;另一种是对通信功能进行扩展。

本文主要针对后者进行具体的描述

本篇文章的结构如下:

1、创建plugin.xml(这是整个插件最关键的文档)

2、创建服务器插件实例(实现Plugin接口的一个类还有一批IQHandler)

3、打包插件(Openfire插件也有自己的打包方式)和部署插件

好滴,实刀实枪的来动手做吧

1、创建plugin.xml

初次开发Openfire和Spark插件的时候,很容易把二者搞混,千万记得,这里是Openfire的plugin.xml不是第二篇文章说的那个啦!

xmlversion="1.0"encoding="UTF-8"?

>

--Mainpluginclass这里是最重要滴-->

com.im.server.plugin.GroupTreePlugin

--Pluginmeta-data-->

GroupTreePlugin

Thisisthegroupplugin.

Phoenix

1.0

14/03/2008

http:

//localhost:

9001/openfire/plugins.jsp

3.4.1

gpl

--Adminconsoleentries-->

--Moreonthisbelow-->

最重要的那一行我已经标记出来啦,就是你这个插件的初始化和垃圾清理类,例子中是在com.im.server.plugin包中的GroupTreePlugin类,下文会对这个类进行详细描述。

其余的都是描述信息,只要你提供了正确的描述信息,一般都不会出错。

建议初次开发者,在写完plugin.xml文件后,写一个简单的Plugin实例,并打印出一些信息,如果重新启动Openfire信息成功显示,恭喜你,你已经迈出一大步了!

2、实现Plugin类和IQHandler

Plugin类主要起到的作用是初始化和释放资源,在初始化的过程中,最重要的的注册一批IQHandler,IQHander的作用有点类似于Spark中的IQProvider,其实就是解析XML文件之后,生成一些有用的实例,以供处理。

下面分别给出一个Plugin类的实例和IQProvider的实例

GroupTreePlugin类

/**

*服务器端插件类

*

*@authorPhoenix

*

*Mar14,200811:

03:

11AM

*

*version0.1

*/

publicclassGroupTreePluginimplementsPlugin

{

privateXMPPServerserver;

/*

*(non-Javadoc)

*

*@seeorg.jivesoftware.openfire.container.Plugin#destroyPlugin()

*/

publicvoiddestroyPlugin()

{

}

/*

*(non-Javadoc)

*

*@seeorg.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware.openfire.container.PluginManager,

*java.io.File)

*/

publicvoidinitializePlugin(PluginManagermanager,FilepluginDirectory)

{

PluginLog.trace("注册群组树IQ处理器");

server=XMPPServer.getInstance();

server.getIQRouter().addHandler(newGroupTreeIQHander());//1

server.getIQRouter().addHandler(newUserInfoIQHandler());

server.getIQRouter().addHandler(newDelUserIQHandler());

server.getIQRouter().addHandler(newCreateUserIQHandler());

server.getIQRouter().addHandler(newAddGroupUserIQHandler());

server.getIQRouter().addHandler(newSetRoleIQHandler());

}

}

上例所示,在初始化中先找到IQRouter,然后通过IQRouter注册一批IQHandler,这些IQHander会自动监听相应命名空间的IQ,然后进行处理;由于这个Plugin不需要做资源释放的工作,所以在destroyPlugin()方法中没有任何内容。

具体的IQHander类如下

GroupTreeIQHander

/**

*处理客户端发来的IQ,并回送结果IQ

*

*@authorPhoenix

*

*Mar14,20084:

55:

33PM

*

*version0.1

*/

publicclassGroupTreeIQHanderextendsIQHandler

{

privatestaticfinalStringMODULE_NAME="grouptreehandler";

privatestaticfinalStringNAME_SPACE="com:

im:

group";

privateIQHandlerInfoinfo;

publicGroupTreeIQHander()

{

super(MODULE_NAME);

info=newIQHandlerInfo("gruops",NAME_SPACE);

}

/*

*(non-Javadoc)

*

*@seeorg.jivesoftware.openfire.handler.IQHandler#getInfo()

*/

@Override

publicIQHandlerInfogetInfo()

{

returninfo;

}

/*

*(non-Javadoc)

*

*@seeorg.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ)

*/

@Override

publicIQhandleIQ(IQpacket)throwsUnauthorizedException

{

IQreply=IQ.createResultIQ(packet);

Elementgroups=packet.getChildElement();//1

if(!

IQ.Type.get.equals(packet.getType()))

{

System.out.println("非法的请求类型");

reply.setChildElement(groups.createCopy());

reply.setError(PacketError.Condition.bad_request);

returnreply;

}

StringuserName=StringUtils.substringBefore(packet.getFrom().toString(),"@");

GroupManager.getInstance().initElement(groups,userName);

reply.setChildElement(groups.createCopy());//2

System.out.println("返回的最终XML"+reply.toXML());

returnreply;

}

}

可以看到主要有两个方法,一个是getInfo()这个方法的目的是提供要解析的命名空间,在本例中,这个IQHandler对每个命名空间为"com:

im:

group"的实例进行处理;还有一个最重要的方法:

handleIQ()该方法对包含指定命名空间的XML进行解析,然后返回一个解析好的IQ。

其实我认为,这个IQHandler和IQ的关系就是Controller和Model的关系(如果你了解MVC的话,那么你一定知道我再说什么),只不过这里并没有指定什么View,你完全可以把IQ当成Model类进行理解。

在这里,我用了GroupManager进行了XML的处理,因为我返回的IQ内容中要从数据库读取所有群组信息,所以转交给GroupManager进行处理,你完全可以在这个方法中进行具体的XML处理,在这里,解析和创建新的XML主要用到的是JDOM(如果你对Java解析XML有所了解,那真的太好了!

)。

程序//1处主要是获取创建返回的IQ,并获取原来IQ的子元素(用于创建我们返回的IQ);程序//2处很关键,如果你不调用createCopy方法,程序会出错(程序会死锁还是什么,忘记咧,不好以西)。

这就是程序的主体部分,我在这里有一个建议,能不用Openfire原始的程序函数,就不要用它们。

我的提取数据库方式都是自己写的Bean,这样有利于你自己对程序的掌控,其实更有利于快速开发(这世道不是啥都讲究敏捷么,哇哈哈)

3、打包插件

打包依然遵循二次打包的原则(如果你不了解啥叫要二次打包,请看上一篇)

这是我的ant文件,由于Eclipse帮我做了build等很多工作,实际我的ant工作就是在打包,并放入插件目录下的plugin文件夹下

xmlversion="1.0"encoding="UTF-8"?

>

value="E:

/workspace/europa/openfire_src/target/openfire"/>

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 中考

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1