Openfire階段實踐總結

来源:http://www.cnblogs.com/5207/archive/2016/06/02/5552726.html
-Advertisement-
Play Games

從3月開始研究Openfire,其實就是要做一套IM系統,也正是這個原因才瞭解到Openfire。之前還真沒想過有這麼多的開源產品可以做IM,而且也沒想到XMPP這個協議竟然如何強大。看來還是標準為先,好的標準可以推動產業發展啊。 Openfire的搭建與簡單的demo之前寫過篇《技術筆記:XMPP ...


從3月開始研究Openfire,其實就是要做一套IM系統,也正是這個原因才瞭解到Openfire。之前還真沒想過有這麼多的開源產品可以做IM,而且也沒想到XMPP這個協議竟然如何強大。看來還是標準為先,好的標準可以推動產業發展啊。

 

Openfire的搭建與簡單的demo之前寫過篇《技術筆記:XMPP之openfire+spark+smack》,當時主要關註的怎麼讓這套體系跑起來吧,只不過現在還是在這個階段,只是多學了點東西留下點筆記吧。

 

1、對於XMPP的學習很重要

最開始覺得搭建一套Openfire+spark太簡單啦,而且將spark的界面修改一下就可以變成一個新的產品,所以當時覺得XMPP協議這麼高深的東西不用太深入。只不過隨著簡單的事情結束了才發現,最核心的還是協議本身,瞭解協議可以更瞭解系統的運作,才能體會到這套系統是有多複雜。當然是對於我來說有點複雜,特別是涉及到前後端結合設計與開始時。

為此我推薦一個國內的XMPP協議翻譯網站:http://wiki.jabbercn.org/%E9%A6%96%E9%A1%B5。

當然如果英文好那就原版吧:http://xmpp.org/about/technology-overview.html

經過一段時間學習後,感覺QQ和微信在基礎原理上真的和XMPP很類似,只是使用的協議格式有些差別,或許這就是即時通訊的抽象層次吧。但是使用XML這種標記語言是不是很浪費流量呢?雖然XMPP擴展起來非常方便,但是就這些標簽也著實夠大的,像平常的文字聊天時,或許中間標記產生的流量也和聊天內容相當了。畢竟我還沒到這種需要考慮大流量的階段,所以這隻是一個想法而已。

2、Openfire的一些設計點與思路

Openfire的源代碼整體看了看還是比較清晰的,擴展上支持插件與組件模式。在最近擴展的中發現openfire的源代碼本身不太好去修改,依賴性很強,唯獨模塊間的依賴比較鬆散些,模塊內的類依賴基本是緊耦合的。只不過Openfire可以通過插件擴展,對源代碼本身的依賴就小了許多,所以說整體來說還是很不錯的。

在Openfire中的插件擴展方式主要是:

  • IQHandler

在XMPP協議中IQ包是指的信息/查詢,可以用於伺服器與客戶端之間進行數據查詢,Openfir中實現了一個IQRouter來處理IQ包。自然IQHandler就是具體的IQ包處理單元啦。IQHandler是基於namespace來進行攔截處理的,自定義自己的命名空間後即可。

IQHandler提供了兩個抽象方法,用於派生類實現:

    /**
     * Handles the received IQ packet.
     *
     * @param packet the IQ packet to handle.
     * @return the response to send back.
     * @throws UnauthorizedException if the user that sent the packet is not
     *      authorized to request the given operation.
     */
    public abstract IQ handleIQ(IQ packet) throws UnauthorizedException;

    /**
     * Returns the handler information to help generically handle IQ packets.
     * IQHandlers that aren't local server iq handlers (e.g. chatbots, transports, etc)
     * return <tt>null</tt>.
     *
     * @return The IQHandlerInfo for this handler
     */
    public abstract IQHandlerInfo getInfo();

handleIQ方法就是解包和業務處理過程,最後返回結果包。

getInfo是用於返回當前IQHandler的命令空間

然後要使這個handler生效還需要註冊到IQRouter,可以在插件啟動時創建IQHandler的對象並add進去:

@Override
    public void initializePlugin(PluginManager manager, File pluginDirectory) {
        iqHandler = new IQGroupChatHander();
        iqRouter = XMPPServer.getInstance().getIQRouter();
        iqRouter.addHandler(iqHandler);
    }

    @Override
    public void destroyPlugin() {
        iqRouter.removeHandler(iqHandler);
    }

 

  • Compoent

Compoent也是一種比較常用的擴展方法,可以通過對特定子域的包進行處理。比如MUC通過註冊不同的Service,每個Service都有一個subdomain,系統會將不同的subdomain的數據包分發到專門服務中處理。這樣就帶來了一個好處,可以完全自定義一套子域的包處理業務,後面實現公眾號訂閱號就想通過這種思路來解決。而且Openfire還有遠程組件的機制,可以擴展成為一個獨立的業務系統,這樣openfire可以只充當消息處理的核心。

具體的應用也比較簡單,實現Component介面,並註冊到ComponentManager中。而Component介面中最為重要的方法就是processPacket方法,代碼如下:

    /**
     * Processes a packet sent to this Component.
     *
     * @param packet the packet.
     * @see ComponentManager#sendPacket(Component, Packet)
     */
    public void processPacket(Packet packet);

註意方法中的參數是Packet,這個表示所有子域下的通訊原語都可以用於這裡處理。

註冊與退出的方法如下:

       componentManager = ComponentManagerFactory.getComponentManager();
        try {
            componentManager.addComponent("subdomain", this);
        }
        catch (Exception e) {
            Log.error(e.getMessage(), e);
            System.err.println(e);
        }

        try {
            componentManager.removeComponent("subdomain");
        } catch (ComponentException e) {
            Log.error(e.getMessage(), e);
        }
  • PacketInterceptor

在Openfire中所以的傳輸都是基於packet,在packet上再派生出不同的通訊原語,如message、roster、JID、IQ等等。基於這個原理只要提供一套對於包的攔截機制就可以實現一套比較強大的擴展機制。在Openfire中就提供了這樣的機制處理。在IQRouter\PresenceRouter\MessageRouter中都提供了對於包的攔截器。

// Invoke the interceptors before we process the read packet
            InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);

攔截器都註冊在InterceptorManager中,在路由處理包時都會調用攔截器,上面的代碼就是在路由中截取的代碼例子。

那麼同樣的實現一個攔截器PacketInterceptor介面,並註冊到InterceptorManager即可。

InterceptorManager.getInstance().addInterceptor(interceptor);

InterceptorManager.getInstance().removeInterceptor(interceptor);

 

有了以上三種方法,Openfire可以發展出各種用法,所以官方自己也實現了放多插件供使用。在此也建議對於openfire的擴展最好還是使用插件吧,除非自己的定製要求很高,Openfire本身已經不適應了的。

我的要求基本都可以達成,而且這樣以後升級新版本也非常簡單,不會出現問題。

3、Spark的糾結

Spark同樣出自於jivesoftware,但感覺擴展上就不那麼好了。也許是我沒有完全弄明白它的擴展原理吧。其實我的需求是重寫Spark的UI,同時加入自己的功能,比如群、訂閱號等。最開始想著Spark也是支持插件的,但是最後改代碼時才發現,裡面依賴太深了,基本上和界面相關的都存在依賴,最後可能都要重寫一套。

其實在Spark中是有一個UIComponentRegistry類的,一些主要的界面都在這個類中註冊的。但可惡的是這些註冊的類大多都不能派生出新類來替換這些註冊的類。比如

private static Class<? extends ChatRoom> chatRoomClass = ChatRoomImpl.class;

這是聊天視窗的註冊類,那麼如果我想寫一個自己的聊天視窗,是不是直接把這個註冊類替換即可呢?不行,因為在其他代碼會盡然會這樣使用

    @Override
    public void filesDropped(Collection<File> files, Component component) {
    if (component instanceof ChatRoomImpl) {
        ChatRoomImpl roomImpl = (ChatRoomImpl) component;

        for (File file : files) {
        SparkManager.getTransferManager().sendFile(file,
            roomImpl.getParticipantJID());
        }

        SparkManager.getChatManager().getChatContainer()
            .activateChatRoom(roomImpl);
    }
    }

在另一個類里盡然直接使用派生類進行了類型判斷,這還只是一個點,類似的點太多了。所以最開始想著通過派生UIComponentRegistry中註冊的類來達到預期目的已經不大可能了。再加上時間有限,也就懶得管這麼多了,就讓開發直接在源代碼上改。

 

可惡的是2.7.7版本升級時發現代碼大變,這個版本升級smack4.x版本,而且大量使用了1.8的新特性。所以又經過了一番代碼合併才升級上來。另外說到smack基本不提供擴展,只提供事件的訂閱。

只不過spark是跨平臺的,很容易就能在mac下運行,而且代碼是java的,暫時還不想拋棄掉,等將來考慮是不是再重寫吧。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 常用快捷鍵 自動生成頭部註釋 代碼片段 NuGet Team Foundation 常用的VS快捷鍵 查看與設置快捷鍵 一般在菜單裡面我們直接就可以看到一些功能的快捷鍵。另外,可以依次通過 菜單欄-工具-選項-環境-鍵盤 中查看和設置對應功能的快捷鍵 推薦幾個我比較常用的快捷鍵 我用的是VS2015 ...
  • 1、頁面後臺代碼添加如下靜態變數: 2、在處理數據的開始,初始化total和startTime變數: 3、在處理數據過程中,不斷累加cur: 4、前端每隔200毫秒獲取進度: 5、後臺計算進度: 效果圖(文字錯了,不是“導入進度”,而是“數據處理進度:”): ...
  • 公司業務量比較大,接了很多項目,為了縮短開發周期老闆讓我牽頭搭建了一個敏捷開發框架。 我們主要的業務是做OA、CRM、ERP一類的管理系統,一個通用的後臺搭出來,再配合一些快速開發的組件開發效率能提高很多。 另外老闆一再強調要支持APP開發,一次開發能部署到安卓和IOS上。 作為開篇之作,先介紹一下 ...
  • 定製路由系統 路由系統是靈活可配置的,當然還可以通過下麵這兩種方式定製路由系統,來滿足其他需求。 1、 通過創建自定義的RouteBase實現; 2、 通過創建自定義路由處理程式實現。 創建自定義的RouteBase實現 創建自定義的RouteBase實現,需要實現一個RouteBase的派生類,而 ...
  • 同Winsock1相比,Winsock2最明顯的就是支持了Raw Socket套接字類型,使用Raw Socket,可把網卡設置成混雜模式,在這種模式下,我們可以收到網路上的IP包,當然包括目的不是本機的IP包,通過原始套接字,我們也可以更加自如地控制Windows下的多種協議,而且能夠對網路底層的 ...
  • 在上一篇文章中我們主要分析了ASP.NET Core預設依賴註入容器的存儲和解析,這一篇文章主要補充一下上一篇文章忽略的一些細節:有關服務回收的問題,即服務的生命周期問題。有關源碼可以去GitHub上找到。 這次的主角就是ServiceProvider一人,所有有關生命周期的源碼幾乎都集中在Serv ...
  • 相信很多人用過MessageBox.show(),是不是覺得這個消息框有點醜呢,反正我是覺得有點醜的,所以我自己重寫了一個。先不說,上兩幅圖對比先: 當然,也不是很好看,不過比原有的好多了。 不多說了,先上xmal代碼: 1 <Window x:Class="MESBox.MEGBox" 2 xml ...
  • 在Web Form 情況下,每一個 ASPX頁面既是一個文件,又是一個隊請求自包含的響應。而在 MVC 情況下,請求是由控制器類中的動作方法處理的,而且與硬碟上的文件沒有一對一的相互關係。 ASP.NET 平臺為了處理 MVC 的 URL,採用了路由系統,它主要有兩個功能: 考查一個輸入 URL(I ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...