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. LINUX关闭防火墙(转载)

    (1) 重启后永久性生效: 开启:chkconfig iptables on 关闭:chkconfig iptables off (2) 即时生效,重启后失效: 开启:service iptables ...

  2. 乱序双发射 和 GHB的分支预测

    乱序执行(out-of-order execution)是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理的技术.比方Core乱序执行引擎说程序某一段有7 条指令,此时CPU ...

  3. Android ExpandableListView使用+获取SIM卡状态信息

    ExpandableListView 是一个可以实现下拉列表的控件,大家可能都用过QQ,QQ中的好友列表就是用ExpandableListView实现的,不过它是自定义的适配器.本篇 博客除了要介绍E ...

  4. HDU 4288 Coder 【线段树+离线处理+离散化】

    题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...

  5. open MMT.distributions = null on transaction type: WIP Lot Split

    open MMT.distributions = null on transaction type:  WIP Lot Split       打开物料事务处理界面,发现事务处理类型为:WIP Lot ...

  6. BZOJ_2002_弹飞绵羊_(LCT)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2002 一列n个数,a[i]表示向后a[i]个,问第k个数进行多少次向后跳跃会飞出去. 分析 i ...

  7. HtmlParser应用,使用Filter从爬取到的网页中获取需要的内容

    htmlparser是一个纯的java写的html解析的库,它不依赖于其它的java库文件,主要用于改造或提取html.它能超高速解析html,而且不会出错.现在htmlparser最新版本为2.0. ...

  8. 从零开始学习jQuery (六) AJAX快餐

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章讲解如何使用jQuery方便快捷的实现A ...

  9. java.util.concurrent.Exchanger应用范例与原理浅析--转载

    一.简介   Exchanger是自jdk1.5起开始提供的工具套件,一般用于两个工作线程之间交换数据.在本文中我将采取由浅入深的方式来介绍分析这个工具类.首先我们来看看官方的api文档中的叙述: A ...

  10. 招商银行支付dll在64位windows系统下的注册使用问题

    按照文档中的说明,注册完dll后,依然报找不到COM组件的错误.尝试过以下方法: 1.在VS中将项目编译目标改为x86,只能解决VS可以启动程序的问题,一部署到IIS中就出错. 2.估计是因为权限问题 ...