Openfire 是一个用Java 实现的XMPP 服务器,客户端可以通过IQ的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack 库提供的各种功能来完成的。其实利用插件方式来扩展Openfire 服务器端主要有两种扩展方式,一种是对服务器控制台页面进行扩展(不是本文的主要内容),即遵循Openfire 页面的布局方式,进行相应的页面扩展和功能扩展另一种是对通信功能进行扩展。本文主要针对后者进行具体的描述。

本篇文章的结构如下:

1、创建plugin.xml(这是整个插件最关键的文档)。
    2、创建服务器插件实例(实现Plugin 接口的一个类还有一批IQHandler)。
    3、打包插件(Openfire 插件也有自己的打包方式)和部署插件。

1、创建plugin.xml

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

 <?xml version="1.0" encoding="UTF-8"?>
<plugin>
<!-- Main plugin class 这里是最重要滴-->
<class>com.im.server.plugin.GroupTreePlugin</class> <!-- Plugin meta-data -->
<name>GroupTreePlugin</name>
<description>This is the group plugin.</description>
<author>Phoenix</author> <version>1.0</version>
<date>14/03/2008</date>
<url>http://localhost:9001/openfire/plugins.jsp</url>
<minServerVersion>3.4.1</minServerVersion>
<licenseType>gpl</licenseType> <!-- Admin console entries -->
<adminconsole>
<!-- More on this below -->
</adminconsole>
</plugin>

最重要的那一行我已经标记出来啦,就是你这个插件的初始化垃圾清理类,例子中是在com.im.server.plugin 包中的GroupTreePlugin 类,下文会对这个类进行详细描述。其余的都是描述信息,只要你提供了正确的描述信息,一般都不会出错。建议初次开发者,在写完plugin.xml 文件后,写一个简单的Plugin 实例,并打印出一些信息,如果重新启动Openfire 信息成功显示,恭喜你,你已经迈出一大步了!

2、实现Plugin 类和IQHandler

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

GroupTreePlugin 类

 /**
* 服务器端插件类
*
* @author Phoenix
*
* Mar 14, 2008 11:03:11 AM
*
* version 0.1
*/
public class GroupTreePlugin implements Plugin
{
private XMPPServer server; /*
* (non-Javadoc)
*
* @see org.jivesoftware.openfire.container.Plugin#destroyPlugin()
*/
public void destroyPlugin()
{ } /*
* (non-Javadoc)
*
* @see org.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware.openfire.container.PluginManager,
* java.io.File)
*/
public void initializePlugin(PluginManager manager, File pluginDirectory)
{
PluginLog.trace("注册群组树IQ处理器");
server = XMPPServer.getInstance(); server.getIQRouter().addHandler(new GroupTreeIQHander()); //
server.getIQRouter().addHandler(new UserInfoIQHandler());
server.getIQRouter().addHandler(new DelUserIQHandler());
server.getIQRouter().addHandler(new CreateUserIQHandler());
server.getIQRouter().addHandler(new AddGroupUserIQHandler());
server.getIQRouter().addHandler(new SetRoleIQHandler());
}
}

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

GroupTreeIQHander 类

 /**
* 处理客户端发来的IQ,并回送结果IQ
*
* @author Phoenix
*
* Mar 14, 2008 4:55:33 PM
*
* version 0.1
*/
public class GroupTreeIQHander extends IQHandler
{
private static final String MODULE_NAME = "group tree handler";
private static final String NAME_SPACE = "com:im:group";
private IQHandlerInfo info; public GroupTreeIQHander()
{
super(MODULE_NAME);
info = new IQHandlerInfo("gruops", NAME_SPACE);
} /*
* (non-Javadoc)
*
* @see org.jivesoftware.openfire.handler.IQHandler#getInfo()
*/
@Override
public IQHandlerInfo getInfo()
{
return info;
} /*
* (non-Javadoc)
*
* @see org.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ)
*/
@Override
public IQ handleIQ(IQ packet) throws UnauthorizedException
{
IQ reply = IQ.createResultIQ(packet);
Element groups = packet.getChildElement();// if (!IQ.Type.get.equals(packet.getType()))
{
System.out.println("非法的请求类型");
reply.setChildElement(groups.createCopy());
reply.setError(PacketError.Condition.bad_request);
return reply;
} String userName = StringUtils.substringBefore(packet.getFrom().toString(),"@");
GroupManager.getInstance().initElement(groups,userName);
reply.setChildElement(groups.createCopy());//
System.out.println("返回的最终XML" + reply.toXML());
return reply;
}
}

可以看到主要有两个方法,一个是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 文件夹下:

 <?xml version="1.0" encoding="UTF-8"?>
<project name="IM" default="release" basedir="."> <property name="openfire.path"
value="E:/workspace/europa/openfire_src/target/openfire" />
<property name="classes.dir" value="classes" />
<property name="lib.dir" value="lib" /> <target name="jar">
<jar jarfile="${lib.dir}/grouptreeplugin.jar" basedir="${classes.dir}" >
<fileset dir=".">
<include name="*.jar"/>
</fileset>
</jar>
<jar jarfile="${openfire.path}/plugins/groupTreePlugin.jar">
<fileset dir=".">
<include name="lib/*.jar" />
<include name="plugin.xml" />
<include name="logo_small.gif" />
<include name="logo_large.gif" />
<include name="readme.html" />
<include name="changelog.html" />
<include name="build.xml" />
</fileset>
</jar> </target> <target name="release" depends="jar">
</target> </project>

开发XMPP IM的更多相关文章

  1. WPF一步步开发XMPP IM客户端1:入门

    [起因&目标] 因为工作原因接触openfire服务端和spark客户端开发,主要是基于openfire扩展开发了针对企业用途的服务器插件,还开发了各个平台上的客户端(Windows\mac\ ...

  2. 手机上使用asmack开发xmpp客户端

    openfire服务端,smack:     下载地址:http://www.igniterealtime.org/downloads/index.jsp     源代码:http://www.ign ...

  3. WPF一步步开发XMPP IM客户端2:主窗体设计

    UI设计方案: 在设计窗体UI之前,先要了解一些主要的接口和帮助类: 对于主窗的左侧列表,容器内的Item必须实现ILeftItem的接口,比如联系人.系统消息.群等,接口包含点击事件 public ...

  4. xmpp整理笔记:xmppFramework框架的导入和介绍

    一个将要开发xmpp的项目,建议在项目刚创建就导入框架,这样可以避免一些自己操作失误造成不必要的损失. xmpp中最常用的框架就是 xmppFrameWork 往期回顾: xmpp整理笔记:环境的快速 ...

  5. XMPP实现登陆注销功能

    XMPP框架的下载与导入等问题请参照 —— XMPP框架的分析.导入及问题解决 DEMO ——XMPP即时通讯(已导入框架)密码:3a7n 这篇我们利用XMPP框架来实现一下登陆功能,先来介绍一下XM ...

  6. 7.xmpp版即时聊天

    即时聊天的解决方案 socket: xmpp:xmpp+openfire+asmack 环信 常见协议 比较安全,tcp上还加了俩层 简单聊一下socket socket:套接字,连接需要ip和端口, ...

  7. 常用开源Jabber(XMPP) IM服务器介绍(转)

      1. Openfire (Wildfire) 3.x授权: GPL or 商用操作系统平台:所有(使用Java开发)XMPP Jabber 协议实现情况:98%Tim 评价:安装和使用非常简单,安 ...

  8. iOS XMPP Framework 中文概述

    本篇文章翻译XMPP Framework中的Overview of the XMPP Framework部分 介绍 The framework is divided into 2 parts: 1. ...

  9. 开源Jabber(XMPP) IM服务器介绍

    一.摘要 这是我粗略读了一遍Jabber协议和相关技术文章后的产物,有些地方不一定准确.在文章中引用的一些代码来自www.jabber.org上的文章. 二. 什么是Jabber    Jabber就 ...

随机推荐

  1. Java集合ArrayList的应用

    /** * * @author Administrator * 功能:Java集合类ArrayList的使用 */ package com.test; import java.io.BufferedR ...

  2. 使用Mybatis Generator自动生成Mybatis相关代码

    本文将简要介绍怎样利用Mybatis Generator自动生成Mybatis的相关代码: 一.构建一个环境: 1. 首先创建一个表: CREATE TABLE pet (name VARCHAR(2 ...

  3. Linux内核中流量控制

    linux内核中提供了流量控制的相关处理功能,相关代码在net/sched目录下:而应用层上的控制是通过iproute2软件包中的tc来实现, tc和sched的关系就好象iptables和netfi ...

  4. matlab numpy equivalents

    THIS IS AN EVOLVING WIKI DOCUMENT. If you find an error, or can fill in an empty box, please fix it! ...

  5. 应付系统选项 Payables Options

    (N) AP > Setup > Options > Payables Options应付系统选项设置整个应付系统使用的控制项和默认值.我们可以在此窗口中设置默认值,从而简化供应商输 ...

  6. Colored Sticks (字典树哈希+并查集+欧拉路)

    Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 27704   Accepted: 7336 Description You ...

  7. C#中窗体的一些简单运用

    从今天开始,我们进入到学window form的知识,今天简单的学习了一些控件和事件的运用.没有什么很全面的理论,所以今天就总结下所写的程序.一个简单的注册页面程序   注册页面程序   要求:   ...

  8. 在Windows中隐藏用户的方法

    这两天新建了一个用户用于共享文件,由于我的电脑只有我一个人用,多了一个用户后在登录界面上觉得挺碍事的,便想把它隐藏起来.找了一下,可以通过如下方式实现: 在注册表编辑器新建项值: HKEY_LOCAL ...

  9. SQL Server登录 18456错误

    1.以windows验证模式进入数据库管理器. 第二步:右击sa,选择属性: 在常规选项卡中,重新填写密码和确认密码(改成个好记的).把强制实施密码策略去掉. 第三步:点击状态选项卡:勾选授予和启用. ...

  10. 使用 Azure Site Recovery 灾难恢复至 Azure 的功能现已正式发布

    ABHISHEK A. HEMRAJANI 云 + Enterprise项目经理 自我们宣布发布使用 Azure SiteRecovery 灾难恢复至 Azure的功能预览版以来,这几个月着实令人 ...