zoukankan      html  css  js  c++  java
  • spark+openfire插件开发(RTX类似的组织架构)

    http://phoenixtoday.blogbus.com/logs/17878527.html

    Spark 是一个基于XMPP 协议,用Java 实现的IM 客户端。它提供了一些API,可以采用插件机制进行扩展,上图中,“部门”部分就是使用插件机制扩展出来的新功能。要想实现你的扩展,首先要了解 Spark API的架构,其中最关键的是要了解它的工厂类,这些工厂类可以获得Spark 提供的诸如XMPPConnection、ChatContainer 等实例,从而你可以实现获取服务器的信息,与另外的Client 通信等功能。最核心的类是SparkManager,这个类是一系列工厂类的工厂类(呵呵,还真拗口)。它的getChatManager()、getSessionManager ()、getMainWindow() 、getConnection() 等方法分别可以获得聊天管理器、会话管理器、主窗口、与服务器的连接等等非常有用的实例。基本上可以说SparkManager 是你与Spark 打交道的衔接口。其实,每一个Manager 都使用了单例模式,你也可以不通过SparkManager 来获取它们,但笔者建议你从单一的入口着手,这样有利于代码的开发和维护。
    接下来描述一下插件的开发流程:
    1、创建插件配置文件 plugin.xml
    2、实现你自己的Plugin 类的实现(如果你需要实现自己规定格式的XML 发送、接收和处理,那么你需要在这里注册你的IQProvider,关于IQProvider 你可以查询Smack API,简单的来讲是处理你自定义的IQ 处理器。)
    3、打包你的插件(Spark 有自己的打包机制,我研究了半天才发现其中的玄机,后面介绍)
    4、部署你的插件(其实3、4两步可以糅合在一起,当然要利用Ant 啦)
    好滴,下面结合一个实际的例子讲述上面的四个步骤
    1、plugin.xml
    <plugin>
        <name>Enterprise IM Client</name>
        <version>1.0</version>
        <author>Phoenix</author>
        <homePage>http://phoenixtoday.blogbus.com</homePage>
        <email>phoenixtoday@gmail.com</email>
        <description>Enterprise Client Plug-in</description>
    <!-- 关键是这里,这里要定义你的Plugin 类 -->
        <class>com.im.plugin.IMPlugin</class>
        <!-- 这里定义你使用的Spark 最低版本 -->
        <minSparkVersion>2.5.0</minSparkVersion>
        <os>Windows</os>
    </plugin>
    这是一个 plugin.xml 文件的内容,插件体系会自动调用你在此文件中定义的Plugin 类,从而完成你自己扩展的功能。最关键的部分我用红色标识出来了,要声明你的插件扩展类,采用完整的命名空间方式(包括包名),其余的部分结合我的注释,大家应该都能理解,就不做详细的描述了。要注意的是plugin.xml 文件要放在项目的根目录下,这是严格规定好的。
    2、Plugin 类的实现
    你的类首先要实现Spark 提供的Plugin 接口,然后实现它的一些方法。其中最主要的是实现initialize() 发放,在这里注册你的的IQProvider
    ProviderManager providerManager = ProviderManager.getInstance();
    providerManager.addIQProvider("groups", "com:im:group", //1
                    new GroupTreeIQProvider());
    System.out.println("注册GroupTree IQ 提供者");
    requestGroupTree();
    上述的代码,就在该类就是我实现的IMPlugin.initialize() 方法中的一小段,大概的含义是,先获取ProviderManager(这个貌似不能从SparkManager 直接获取),然后注册一个GroupTreeIQProvider(自己创建的)这是一个IQProvider 的具体实现,它用于解析像下面这样的一个XML 文件:
    <?xml version="1.0" encoding="UTF-8"?>
    <iq type='result' to='domain@server.com' from='phoenixtoday@gmail.com' id='request_1'>
        <groups xmlns='com:im:group'>
            <group>
                 <groupId>1</groupId>
                 <name>西安交通大学</name>
                 <upGroup>ROOT</upGroup>
                 <isLeaf>0</isLeaf>
                 <description>xjtu</description>
                 <user>
                     <userGroupId>1</userGroupId>
                     <userName>phoenix_test</userName>
                     <role>normal</role>
                 </user>
            </group>
            <group>
                 <groupId>2</groupId>
                 <name>电信学院</name>
                 <upGroup>1</upGroup>
                 <isLeaf>1</isLeaf>
                 <description>xjtu info</description>
            </group>
        </groups>
    </iq>
    可以看到,在注册 IQProvider 的时候(代码中标注的1部分),需要你提供名称和命名空间,我的XML 文件中的iq 下的第一个子节点是<groups> 所以我的名称就写“groups”,命名空间对应于groups 节点的xmlns(XML Name Space)所以是“com:im:group”,其实IQProvider 中最关键的方法是parseIQ(XmlPullParser parser) 该方法就是解析XML,完成你的功能,并返回一个相应的IQ 实例(这里可以把IQ 看做一个回馈的Model 类)。说到底实现基于XMPP 协议的IM 就是解析XML 文件,而这正是客户端的IQProvider 和服务器端的IQHandler(下一篇文章会涉及到)所做的事情。
    3、打包你的插件
    现在该有的功能都实现了,那么就是打包了。这最好利用Ant 来完成,因为每次你都要打包,要部署,如果纯手动的话,那也太不敏捷了,大大影响开发效率。
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="IM" default="release" basedir=".">
        <property name="src.dir" value="src" />
        <property name="dest.dir" value="bin" />
        <property name="lib.dir" value="lib" />
        <property name="im.path"
            value="E:/workspace/europa/spark_new/doc/spark/target/build" />
        <target name="clean">
            <!-- 
                <delete dir="${dest.dir}" />
                <delete dir="${lib.dir}" />
            -->
        </target>
        <target name="init" depends="clean">
            <!-- 
                <mkdir dir="${dest.dir}" />
                <mkdir dir="${lib.dir}" />
            -->
        </target>
        <target name="build" depends="init">
            <!--
                <javac srcdir="${src.dir}" destdir="${dest.dir}" />
            -->
        </target>
    <!-- 最重要的是这里,打两次包 -->
        <target name="jar" depends="build">
            <jar jarfile="${lib.dir}/eim.jar" basedir="${dest.dir}" />
            <jar jarfile="${im.path}/plugins/eim.jar">
                <fileset dir=".">
                    <include name="lib/*.jar" />
                </fileset>
                <fileset dir=".">
                    <include name="plugin.xml" />
                </fileset>
            </jar>
        </target>
        <target name="release" depends="jar">
            <!-- 
                <exec executable="cmd.exe"
                failonerror="true">
                <arg line="/c e:"/>
                <arg line="/c cd workspace\europa\spark_new\doc\spark\target\build\bin"/>
                <arg line="/c startup.bat"/>
                </exec>
            -->
        </target>
    </project>
    这是我的这个项目的 build.xml 文件中的内容。因为Eclipse 其实帮我自动完成了编译的任务,所以我也就省去了这写编译的步骤,最重要的是大家要看到“jar” 部分,Spark 打包的神秘之处也就在此,打两次包首先把你的项目打包到本项目lib 文件夹下,比如说你的项目目录是MyPlugin 那么,你就将你的类打包到MyPlugin/lib 目录下,然后再次的打包,将所有的lib 文件夹下的内容打包起来,记得这次要包含plugin.xml。也就是说,最后Spark 插件体系会读取你的项目下的lib 文件夹下的内容。这里我也有个疑问,我本来想每次打包后自动执行bat 文件,启动插件,看看效果,为啥死都调用不了呢,那段代码在最后面,注释掉了,谁能帮我解决,我请他吃饭滴!
    4、最后就是发布了
    其实我的发布很简单,就是将这个打包好的jar 文件拷到Spark 本身的plugins 目录下,每次启动Spark 的时候,它会自动调用自定义的插件的。我这里用Ant 第二次jar 的时候,就自动拷贝过去了,这里用的是绝对路径,所以你不能直接拷贝就用滴呦(是不是很丑陋呀,这段Ant 代码)。
    基本上客户端的实现原理就是这样的,只是有些地方需要特别注意,还有就是应该利用像Ant 这样的工具大大简化开发步骤,加快开发效率。还有就是,我建议你在开发自己的插件的时候,多利用MVC 模式,尤其是在IQProvider 解析后,生成的部分可以实例化Model,然后你可以编写自己的Manager 进行这些Model 的处理。多写Log,当然Log4j 貌似不太起作用,那就System.out.println() 吧,哈哈!今天就写到这里啦,偶有点累啦。

  • 相关阅读:
    忍道
    2020.12.27
    2020.12.26
    2020.12.25
    记录
    卸载抖音
    汉化报告修改配置文件
    tcp校验client客户端的合法性
    tcp连接发送命令客户端接收后返回结果给服务端
    logging模块
  • 原文地址:https://www.cnblogs.com/IamThat/p/3056031.html
Copyright © 2011-2022 走看看