`

openfire插件开发

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

本篇文章的结构如下:

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

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

1、创建plugin.xml

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

view plaincopy to clipboardprint?
<?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> 

<?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 类

view plaincopy to clipboardprint?
public class GroupTreePlugin implements Plugin  
{  
    private XMPPServer server;  
 
    public void destroyPlugin()  
    { }  
 
    public void initializePlugin(PluginManager manager, File pluginDirectory)  
    {  
        PluginLog.trace("注册群组树IQ处理器");  
        server = XMPPServer.getInstance();  
          
        server.getIQRouter().addHandler(new GroupTreeIQHander()); 注:1 
        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());  
    }  


public class GroupTreePlugin implements Plugin
{
    private XMPPServer server;

    public void destroyPlugin()
    { }

    public void initializePlugin(PluginManager manager, File pluginDirectory)
    {
        PluginLog.trace("注册群组树IQ处理器");
        server = XMPPServer.getInstance();
       
        server.getIQRouter().addHandler(new GroupTreeIQHander()); 注:1
        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

view plaincopy to clipboardprint?
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);  
    }  
 
    @Override 
    public IQHandlerInfo getInfo()  
    {  
        return info;  
    }  
 
    @Override 
    public IQ handleIQ(IQ packet) throws UnauthorizedException  
    {  
        IQ reply = IQ.createResultIQ(packet);  
        Element groups = packet.getChildElement(); 注:1 
          
        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()); 注:2 
 
        System.out.println("返回的最终XML" + reply.toXML());  
 
        return reply;  
    }  


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);
    }

    @Override
    public IQHandlerInfo getInfo()
    {
        return info;
    }

    @Override
    public IQ handleIQ(IQ packet) throws UnauthorizedException
    {
        IQ reply = IQ.createResultIQ(packet);
        Element groups = packet.getChildElement(); 注:1
       
        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()); 注:2

        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 文件夹下

view plaincopy to clipboardprint?
<?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> 

<?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+Spark+Openfire 的插件开发三部曲彻底结束了,希望你们对这个开发流程有了系统的了解。

分享到:
评论

相关推荐

    openfire插件开发环境搭建

    标题中的“openfire插件开发环境搭建”是指学习和配置Openfire服务器以开发自定义插件的过程。Openfire是一款开源的即时通讯服务器,基于XMPP(Extensible Messaging and Presence Protocol)协议,允许用户进行实时...

    openfire插件开发(1)

    OpenFire插件开发系列的第一部分主要涉及如何搭建OpenFire的二次开发环境,为后续的插件开发工作做好准备。OpenFire是一款开源的即时通讯服务器,它基于Java技术,支持XMPP协议,允许开发者通过编写插件来扩展其功能...

    openfire 插件开发

    综上所述,Openfire插件开发涵盖了一系列技术点,包括对XMPP协议的理解,Java编程技能,Maven项目管理,以及Openfire提供的各种API和工具。通过这些技术,开发者可以构建出强大的、定制化的即时通讯解决方案。

    Openfire插件开发 访问jsp servlet

    在这个“Openfire插件开发 访问jsp servlet”项目中,我们将探讨如何在Openfire环境中开发一个插件,同时利用JavaServer Pages(JSP)和Servlet技术来处理HTTP请求。 首先,让我们理解Openfire插件开发的基本流程:...

    OpenFire插件开发从入门到精通

    本篇文章将深入探讨OpenFire插件开发,旨在帮助开发者从入门到精通,实现移动互联聊天服务器的高效搭建。 首先,了解OpenFire的基本架构至关重要。OpenFire基于XMPP协议,该协议是互联网工程任务组(IETF)定义的一...

    openfire插件开发人员指南

    以下是对Openfire插件开发核心概念的详细解释: 1. **插件结构**: 插件的基本结构包括一个包含所有必要组件的文件夹。其中,`plugin.xml`是定义插件的关键文件,`readme.html`和`changelog.html`是供用户查看的...

    openfire插件开发.pdf

    文档中提到了1.5和1.6版本的JDK,这两个版本都是较早的版本,但足以应对Openfire插件开发的需求。Openfire插件开发时可能要根据使用的JDK版本调整代码,以确保兼容性。 在数据库方面,文档提到了MySQL 5.0版本,这...

    编写Openfire开发插件、部署源码

    总的来说,Openfire插件开发涉及到Java编程、数据库设计、XML配置以及Web服务的构建。开发者需要熟悉XMPP协议、Java编程和Web开发的相关知识,才能有效地利用Openfire的API进行插件开发。而部署源码则涉及到构建流程...

    Openfire插件开发人员指南

    总结来说,Openfire 插件开发的关键在于理解 `plugin.xml` 文件的结构和内容,以及如何组织和编写 Java 类以实现所需功能。通过熟练掌握这些知识,开发者可以轻松地扩展 Openfire 的功能,满足特定的业务需求。从...

    openfire服务器开发插件的简单demo

    总的来说,Openfire插件开发涉及Java编程、XML配置、服务器端API的使用等多个方面,是一个综合性的技术实践。通过不断学习和实践,你将能够创建出满足特定需求的Openfire插件,丰富和拓展Openfire的功能。

    XMPP协议及其服务器端的Openfire插件开发.doc

    综上所述,XMPP协议及其服务器端的Openfire插件开发是构建现代即时通讯系统的重要组成部分,通过XML的灵活性和标准化的优势,它为开发者提供了强大的工具,以创建高度定制化且与各种平台兼容的通信解决方案。

    Openfire插件开发实例

    目的:主要是为了监控Openfire各类message,然后对message body做进一步...局限:因为时间有限,本插件并没有对Openfire message协议进行扩展,都是基于原生的xml协议,因此后续开发还需要进行更加深入的二次开发操作。

    第一个openfire插件源码及说明

    通过这个简单的教程,初学者可以快速上手Openfire插件开发,理解其核心原理,并逐渐掌握更复杂的插件功能。随着经验的积累,你将能够开发出满足各种需求的Openfire插件,丰富和增强Openfire服务器的功能。

    Openfire 及插件开发 . 国内没有中文资料.我自己手写

    JMS(Java Message Service)可能是用于实现异步通信或消息队列的组件,而Spark是一个基于XMPP的桌面聊天客户端,也可能与Openfire插件开发有关。 总之,Openfire插件开发需要开发者具备Java编程基础、XML配置知识...

    openfire 插件简单示例

    本示例将带你走进Openfire插件开发的世界,通过一个简单的Servlet插件来介绍开发流程。 首先,我们需要理解Openfire插件的基本结构。一个Openfire插件通常包含以下几个部分: 1. **Plugin.java**:这是插件的核心...

    openfire插件

    在"openfire_plugin"这个压缩包中,我们很可能会找到一系列与Openfire插件开发相关的源代码文件。这些文件通常包含以下几个部分: 1. **主类(Main Class)**:这是插件的核心部分,负责加载和初始化插件。它继承自...

    openfire简单插件

    **一、Openfire插件开发环境搭建** 在开始开发之前,我们需要搭建Openfire源码环境。首先,你需要在Openfire官网(https://www.igniterealtime.org/projects/openfire/)下载源码。解压后,利用Eclipse或IntelliJ ...

    Openfire 的安装和配置、插件开发

    Openfire 安装配置和插件开发详解 Openfire 是一个基于 XMPP 协议的即时通信服务器,可以实现实时的聊天服务。在本文中,我们将详细介绍 Openfire 的安装和配置过程,并探讨如何使用 Eclipse 进行插件开发。 一、...

Global site tag (gtag.js) - Google Analytics