首先要了解smack中兩個客戶端是如何交流的,它們通過連接服務器,通過服務器來進行交流。而客戶端和服務器交流時,會打開一個<stream>流,通過在<stream>中加入一些包的xml信息進行交流,當斷開後會用</stream>結束。
簡單寫一下:
<stream>
<message .....
<presence..
...
</stream>
而smack和openfire開源服務器都是用java實現的,java是面向對象的語言,如何將xml中的信息包,提取成對象呢,於是smack提供了ProciderManager。
而關於PrividerManager主要提供了兩種提供者(我個人理解爲解析器)
1.IQProvider 負責將stream流中iq請求解析成對象。
2.PacketExtensionProvider 將附屬在在信息包(如message,IQ,presence)中含有的子文檔解析成對象。
上面兩個解析器都會講元素名,命名空間,對應的類或Bean,被保存在你的JAR文件的META-INF目錄下創建的smack.providers下。
ProviderManager pm = ProviderManager.getInstance();
IQProvider
在代碼中的實現:
pm.addIQProvider("query", "jabber:iq:time",
Class.forName("org.jivesoftware.smackx.packet.Time"));//向smack.providers中註冊
在smack.providers的存在形式:
<?xml version="1.0"?>
<smackProviders>
<iqProvider>
<elementName>query</elementName>
<namespace>jabber:iq:time</namespace>
<className>org.jivesoftware.smack.packet.Time</className>
</iqProvider>
</smackProviders>
在stream流解析的內容:
<stream>
...
<iq type='result' to='[email protected]' from='[email protected]' id='time_1'>
<query xmlns='jabber:iq:time'>
<utc>20020910T17:58:35</utc>
<tz>MDT</tz>
<display>Tue Sep 10 12:58:35 2002</display>
</query>
</iq>
...
</stream>
以上的原理,通過向Provider實例中添加IQ解析器,將內容添加到smack.Providers文件中,當解析<stream>流中的iq包時,會將iq包的內容封裝到一個實體中,當然,該實體必須有setUtc,setTx,setDisplay方法。IQProvider類可以實現IQProvider接口或繼承IQ類,進行自己定義。
PacketExtensionProvider
在代碼中的實現:
pm.addExtensionProvider("x", "jabber:x:roster",
new RosterExchangeProvider());//向smack.providers中註冊
在smack.providers中存在的形式:
<smackProviders>
<extensionProvider>
<elementName>x</elementName>
<namespace>jabber:iq:event</namespace>
<className>org.jivesoftware.smack.packet.MessageEvent</className>
</extensionProvider>
</smackProviders>
在stream流中的信息包中
<iq type='result' to='[email protected]' from='[email protected]' id='time_1'>
<query xmlns='jabber:iq:time'>
<utc>20020910T17:58:35</utc>
<tz>MDT</tz>
<display>Tue Sep 10 12:58:35 2002</display>
</query>
<x xmlns='jabber:iq:event'>
<a>20020910T17:58:35</utc>
</x>
</iq>
在信息包中發現了子信息包,將向smack.providers中查找該子信息包的解析器,進行解析.IQProvider類可以實現PacketExtensionProvider接口或一個標準Bean,進行自己定義。
借鑑的文章地址:http://blog.sina.com.cn/s/blog_54ef39890100ueq4.html