關於cometd的一些使用經驗
一:js端使用方式
===================================================
第一步 :初始化cometd配置,
$.cometd.configure({
url: cometdURL,
logLevel: 'debug'
});
有兩種方式:
===================================================
一:經過 URL string
cometd.configure('http://localhost:8080/cometd');
二:經過配置對象的方式:
cometd.configure({
url: 'http://localhost:8080/cometd'
});
經過第二種方式配置cometd時,對象屬性以下:
url:鏈接URL
logLevel:日誌級別,默認爲info,可支持warn、info、debug
maxConnections:客戶端鏈接到cometd服務端最大鏈接數量,默認爲2,根據瀏覽器的不一樣,能夠更改瀏覽器默認支持最大鏈接的相應值
backoffIncrement:與服務器鏈接失敗後,等待重連的增量時間,默認爲1000,單位爲毫秒。如:第一次重連爲1s,則第二次重連爲2s之後,第三次3s,以此類推
maxBackoff:最大重連增量時間,默認爲60000ms
reverseIncomingExtensions:
maxNetworkDelay:一個request請求鏈接服務器失敗的最大等待時間,默認爲10000ms
requestHeaders:request請求頭,默認爲{}
appendMessageTypeToURL:是否支持Bayeux消息類型能夠被附加到URL上併發送至服務器,默認爲true
autoBatch:當沒有手動指定批次處理一批publish通信消息時,是否支持默認的批處理,默認爲false
===================================================
第二步:調用 $.cometd.handshake()方法,與服務器通信握手
===================================================
調用configure後,並無啓動Bayeux Communication,須要手動調用comted.handshake()進行通信握手,通信握手作了兩件事情:
1.客戶端與服務器協定通信協議類型
2.通信協議類型達成一致後,服務端通知客戶端詳細的請求時間
該方法是一個異步方法,在通信握手完成後會當即返回,可是handshake返回後並不表明鏈接已經創建,通信握手失敗緣由可能有以下幾個:
1.輸錯了訪問的URL
2.客戶端與服務器沒有交換成功通信協議
3.服務器拒絕通信握手,例如:證書認證失敗等
4.服務器down掉
5.網絡傳輸失敗
另外:cometd提供init()方法,集成了configure和handshake方法
因爲handshake是異步的方法,你沒法獲知鏈接是否創建成功,即便創建成功,客戶端也有可能被中斷,例如服務器down機等緣由。cometd提供了監聽機制,用來監聽鏈接等特殊通道的狀態
===================================================
第三步:訂閱消息通道Channels,創建監聽
subscribe 訂閱普統統道消息、service通道消息
addListener 監聽meta channels消息
===================================================
Bayeux 對Channels定義爲:Channels相似於一個消息主題,有興趣的人能夠訂閱該消息通道,並接收消息通道發佈過來的消息。
Channels有三種:
1.meta channels(元數據channel,全部此種channel都以/meta開頭)
2.service channels(服務channel,全部此種channel都以/service開頭)
3.normal channels(普通channel)
每一個channel相似於一個目錄的路徑,例如/meta/connect
&& meta channels
meta channels是由Bayeux 協議自身創建的,開發時不能subscribe一個meta channel,不然服務器迴響應錯誤的信息,可是你能夠在meta channel上創建一個監聽
向一個meta channels發送消息是毫無心義的,只有Bayeux協議建立並在meta channel上面傳輸信息
meta channels一般用在客戶端監聽錯誤信息上,例如:通信握手錯誤,網絡鏈接錯誤等。
&& service channels
service channels 一般用在服務端與客戶端request/response通信模式下,它與消息通知/訂閱通信模式與普通channel大相徑庭。
當訂閱服務通道而且沒有獲得錯誤的響應時,此時服務端未處理任何操做,而且忽略了訂閱請求。
你可使用一個服務器與客戶端之間特定的語義,將消息發佈到service channels。
service channels一般用來實現私聊。
&& normal channels
普通channels一般創建一個消息主題,並使用在publish/subscribe通信模式下。你能夠在普通channel上進行訂閱及消息發佈。
普通channel一般用來向全部訂閱的客戶端發送主題消息,例如當股票價格發生波動的時候。
addListener()方法:
1.必須用在監聽meta channels消息
2.可能會用在監聽service channels消息,(也可使用subscribe()方法,可是不被推薦使用)
3.不能用來監聽normal channels消息,(通常使用subscribe()方法來替代)
4.不能涉及任何與服務器的通信,這樣能夠在調用handshake()以前調用。
5.是一個同步方法, 當它返回值時,必須保證listener已經添加。
subscribe()方法:
1.不能用在監聽meta channels消息,不然服務器回返回錯誤。
2.可能會用在監聽service channels消息,(也可使用addListener()方法,推薦使用)
3.用來監聽normal channels消息
4.包含於服務器的通信,在handshake被調用以前不能調用它
5.是一個異步的方法,在服務器收到並處理訂閱請求以前當即返回。
注意:調用subscribe方法並不意味着當該方法返回值的時候你已經完成了服務器的訂閱。
addListener和subscribe方法分別返回兩個訂閱對象能夠傳遞給removeListener()和unsubscribe()方法。
// Some initialization code
var subscription1 = cometd.addListener('/meta/connect', function() { ... });
var subscription2 = cometd.subscribe('/foo/bar/', function() { ... });
// Some de-initialization code
cometd.unsubscribe(subscription2);
cometd.removeListener(subscription1);
/////////////////////////////////////
var _subscription;
// The idempotent method
function _refresh()
{
_appUnsubscribe();
_appSubscribe();
}
function _appUnsubscribe()
{
if (_subscription)
cometd.unsubscribe(_subscription);
_subscription = null;
}
function _appSubscribe()
{
_subscription = cometd.subscribe('/foo/bar', function() { ... });
}
////////////////////////////////////////
值得注意的是,你要當心處理你的應用。爲了不泄露函數調用或者避免函數屢次調用(一旦你屢次錯誤的綁定了相同的回調函數)
當服務器端未返回信息時(網絡中斷或者服務器crash時),subscribe和unsubscribe方法會有什麼樣的行爲?
subscribe:本地監聽者首先加入到channel中的訂閱者列表中,而後與服務器通信。若是通信失敗,服務器並不知道須要向客戶端發送數據所以客戶端本地的監聽者並不會被反調。
unsubscribe:本地監聽者首先從channel中斷訂閱者列表中移除。而後嘗試與服務器通信。若是通信失敗,服務器仍然發送信息到客戶端,可是本地並無響應監聽可指達。
關於監聽者異常處理問題:
若是監聽者/訂閱者函數拋出異常,錯誤信息會以debug級別打印日誌。然而,你能夠定義一個全局異常監聽處理函數來截獲異常信息。
當監聽者或者訂閱者每次拋出異常時該全局方法都會被反調。
cometd.onListenerException = function(exception, subscriptionHandle, isListener, message)
{
// Uh-oh, something went wrong, disable this listener/subscriber
// Object "this" points to the CometD object
if (isListener)
this.removeListener(subscriptionHandle);
else
this.unsubscribe(subscriptionHandle);
}
全局異常監聽機制可能會向服務端發送消息。若是異常監聽處理函數拋出了異常,異常會以info級別的日誌形式
打印出來,Cometd框架不會break掉。
////////////////////////////////////
使用通配符能夠同時訂閱多個渠道,例如:
cometd.subscribe("/chatrooms/*", function(message) { ... });
單個星號統配單一渠道段,如:/chatrooms/12 /chatrooms/15 不支持/chatrooms/12/upload
爲了統配多渠道段,可使用雙星號,如:
cometd.subscribe("/events/**", function(message) { ... });
使用多渠道可支持相似/events/12/upload events/12 events/12/upload/abc等通道
通配符原理一樣應用在監聽者中,例如:
cometd.addListener("/meta/*", function(message) { ... });
默認的,訂閱總體通配符/*和/**會發生錯誤,通配符只能放在分段的最後面。
目前爲止最有趣的meta channels 是 /meta/connect,由於服務器能夠返回當前鏈接的狀態。
值得一提的是,meta/connect也被用於長輪詢服務器。所以,若是在一個有效的輪詢中發佈一個斷開消息,
服務器會返回該poll並觸發/meta/connect linstener。
=============================================================
第四步 調用publish方法向通道中發佈消息
=============================================================
publish方法容許你向某一特定的channel中發佈消息
cometd.publish('/mychannel', { mydata: { foo: 'bar' } });
不能發佈消息到meta channel,可是能夠發佈消息到一個未訂閱的channel,前提是你已經handshake了
publish是一個異步的通信方法,在服務器收到消息以前它會當即返回。
=============================================================
關於disconnecting
=============================================================
cometd js api提供了自動重連功能當網絡或服務器鏈接失敗時。重連參數在configuration中配置
1.短暫網絡鏈接失敗
一旦發生網絡暫時鏈接失敗,客戶端會經過/meta/connect通道發佈消息,並將successful標誌位置爲false。
此時服務器會保持客戶端的狀態,一旦網絡回覆鏈接,服務器會恢復鏈接就像未發生中斷同樣。
客戶端在這種狀況下,僅僅須要從新創建長輪詢,可是在網絡中斷期間發佈給服務器的消息不會被重發。
2.長時間網絡異常或服務器異常
若是網絡鏈接長時間異常,服務器將會超時並失去客戶端鏈接,並刪除與之相關的狀態。
在這種狀況下,客戶端的重連機制將會執行如下步驟:
。。長輪詢試圖從新創建,可是服務器拒絕訪問並返回402::Unknown client錯誤信息
。。通信握手試圖從新創建,服務器一般會接收,並從新創建一個鏈接
。。在通信握手創建成功的基礎上,長鏈接從新創建。
若是註冊了meta channels,瞭解這些步驟,由於從新鏈接可能會涉及多個服務器的消息交換。
調用disconnect函數致使消息被髮送給Bayeux服務端,以便服務端清理關於該客戶端的狀態維護。
正如全部涉及到與服務器通信的方法同樣,它是一個異步的方法。若是服務器並未返回,js端將會中止全部的試圖的鏈接,而且清理本地狀態。
無論disconnect方法返回成功或者失敗,該方法都是安全的。客戶端不管如何都會disconnect,它的本地狀態會被清理掉。
若是服務器沒有返回值,最終該客戶端將會被超時處理,而且清理服務端的狀態。
=============================================================
關於message bantching
=============================================================
咱們常常須要向服務器不一樣的渠道同時發送數據。因爲publish方法是異步的,同時向服務器端發佈屢次時,並不能一塊兒發佈並依次返回。
咱們曾天真的這樣處理:
cometd.handshake();
// Warning: non-optimal code
cometd.publish('/channel1', { product: 'foo' });
cometd.publish('/channel2', { notificationType: 'all' });
cometd.publish('/channel3', { update: false });
你可能認爲,三個publish方法會相繼的從客戶端發出,可是實際並不是如此。publish方法是異步的,它會當即返回值。所以3個publish方法可能在未返回任何數據以前到達網絡。
以上發生的是,第一個publish方法會當即執行,另外兩個放入隊列中,等待第一個publish執行完成。
當服務端接收到publish發送過來的消息時,第一個publish執行完成,服務器返回meta信息給客戶端。客戶端接收該信息並完成publish方法。
當第一個publish完成後,第二個被執行並等待完成,以後第三個被執行。
若是configuration參數autoBatch設置爲true,應用程序會自動執行批次裏面已排隊的消息。
所以,在上面的例子中,若是autoBatch設置了true,第一個publish方法會當即被執行,當它執行完成後,
應用程序會將第二個和第三個publish打包成一個請求發送到服務器。
這種排隊機制是爲了不在長輪詢後面發起publish隊列,若是沒有這個機制,瀏覽器會受到3個發佈請求,可是隻能有2個連接,
一個是已經被佔用的長輪詢請求。所以瀏覽器可能會決定循環發送request,因此第一個publish發生在第二個鏈接中(第一個已經
忙於長輪詢請求),調度第二個publish使用第一個鏈接,第三個publish使用第二個鏈接,當第一個publish返回後。
結果是,若是你有一個超時時間爲5分鐘的長鏈接,第二個publish請求可能比第一個和第三個publish晚5分鐘到達服務器。
你可使用batching優化這三個publish請求,經過將消息綁定成組造成一個單一的Bayeux消息。
cometd.handshake();
cometd.batch(function()
{
cometd.publish('/channel1', { product: 'foo' });
cometd.publish('/channel2', { notificationType: 'all' });
cometd.publish('/channel3', { update: false });
});
// Alternatively, but not recommended
cometd.startBatch()
cometd.publish('/channel1', { product: 'foo' });
cometd.publish('/channel2', { notificationType: 'all' });
cometd.publish('/channel3', { update: false });
cometd.endBatch()
當一個batch啓動後,隨後的API調用將再也不發送到服務器,而是會排隊等候,直到batch結束。
batch將全部的排隊等候的message包裝成單一的一個Bayeux消息併發送至Bayeux服務器。
消息綁定有效的利用了網絡,將三個request/response生命週期縮短成一個。
=============================================================
關於transports
=============================================================
Bayeux規範定義了兩個強制性的傳輸協議:
long-polling和callbak-polling
cometd實現了這兩個協議,並支持websocket協議。
最新的瀏覽器(如火狐3.5+),也有可能使用長輪詢通訊及跨站點通信。
1.long-polling transport
long-polling transport是瀏覽器和服務器之間默認的通信協議,若是不支持websocket的話。
該協議應用在跨域名及相同域名的客戶端、服務器通信。數據類型被組織成text/json格式並經過一個普通的XMLHttpRequest推送至服務器。
2.callback-polling transport
callback-polling transport應用在跨域名通信。衆所周知,XMLHttpRequest訪問不一樣域中的腳本是有限制的。
二 java端
=========================
基本概念
=========================
Cometd java端的實現創建在流行的jetty http服務器及servlet容器上。儘管它基於jetty,可是
它也能夠簡便的移植到其餘2.5及以上的servlet容器(由於它使用了便攜式的jetty continuation api)。
使用了cometd的war包能夠部署到除jetty外的其餘servlet2.5容器上,可是應用較少,由於它會減弱與servlet的集成。
當部署在servlet3.0容器上時,cometd app將會使用servlet容器提供的異步特性。並具備充分的便攜性及高擴展性。
cometd java實現提供了一個客戶端包和服務端包。
java cometd 基本概念
comtd技術使用Bayeux協議提供的可伸縮的基於HTTP通信的消息傳遞來實現。
通常來講,消息系統是經過一個網絡協議通信的客戶端和服務端組成。這種捕獲模式成爲半對象加協議。
Sessions
Client-session是表明與Bayeux服務器通信會話的客戶端的一半對象。客戶端創建session對象後,最初與服務端的SeverSession並沒有關聯。
只有當客戶端session與服務端通信握手,此時建立響應的服務器會話,並建立兩個半對象之間的關係。
client-session對象直接指向遠程的客戶端,但它也一樣存在於服務端。Bayeux服務器只知道server session半對象,惟一建立server Session辦對象的途徑是首先創建它的客戶端session通信者,並經過server通信握手。
爲此,在服務端有一個附加的概念:LocalSession。它集成自ClientSession。LocalSession是一個存在於服務端的client Session,它是服務端本地的對象。
例如:服務端的services與local session關聯在一塊兒。在服務端service創建以前,local session進行通信握手並創server session半對象通信服務。所以Bayeux服務端能夠經過ServerSession以一樣的方式處理遠程的session和local session。
在cometd中,兩個半對象經過交換信息來通信。
message
java api提供了服務端的消息接口,用來進行只讀信息的交互。
用戶能夠修改消息內容,Message的內置子接口Mutable經過回調函數的參數使用。
在服務端,內置接口ServerMessage容許信息只讀的交互,Mutable內置接口被做爲回調函數的參數傳送。
message被用來在channel裏面傳送。
channel
channel被定義爲消息的主題,消息能夠發送給全部訂閱該主題並可接收主題信息的人。
在服務端,ServerChannel子接口容許與channel進行交互,例如經過發佈消息或者增長監聽者。
=================================
cometd java 服務端配置
=================================
BayeuxServer和服務傳輸協議參數能夠在web.xml中做爲CometdServlet的初始化參數來配置。
當CometD servlet建立了BayeuxServer實例後,servlet的初始化參數會經過BayeuxServer實例轉變成服務傳輸協議配置。
ComtedServlet必須在web.xml裏配置,不然服務器不能使用Bayeux協議。一般將路徑配置成/cometd/*,可是能夠更改url-pattern路徑。
BayeuxServer 配置文件
logLevel 默認0 0=off 1=config 2=info 3=debug
transports 默認空 以逗號分隔的ServerTransport實現類,這些實現類新增至默認的server transport上
allowedTransports 默認空 以逗號分隔的能夠容許使用的ServerTransports實現類,若是未特殊說明,默認的通信將被容許。
Server Transport Configuration
cometd 2中,服務協議能夠經過插件化參數的形式配置,它可使用指定的前綴來配置不一樣的協議參數。
例如,timeout參數沒有任何前綴,所以它對全部的協議都有效,long-polling.jsonp.timeout參數重寫了timeout參數,該參數對callback polling協議有用。
timeout 默認:30000ms 服務器將空數據包響應至一個長輪詢前等待接收消息的最大時間
ws.timeout 默認:15000ms 相似於timeout參數,僅對websocket協議生效
interval 默認:0ms 指定客戶端在一個長輪詢結束到下一個長輪詢開始之間的等待時間
ws.interval默認:2500ms相似於interval,僅對websocket協議生效
maxInterval默認:10000ms在客戶端被認爲失效及離開以前,服務端等待客戶端長輪詢的最大時間
ws.maxInterval 默認:15000ms 相似於maxInterval,僅對websocket生效
maxLazyTimeout 默認:5000ms 服務器等待lazy消息發佈的最大時間
metaConnectDeliverOnly 默認:false 傳輸協議是否只能經過long poll方式傳遞信息
jsonDebug 默認:false 是否打開debug
maxSessionsPerBrowser 默認:1 每一個瀏覽器可容許的最大session數量,
allowMultiSessionsNoBrowser 默認:false 當瀏覽器未被檢測到時是否容許多個Sessions
multiSessionInterval 默認:2000
Advanced Configuration
若果你使用的是jetty 7,你可能會想配置CrossOriginFilter
跨站腳本訪問
Authorization(身份認證)
Bayeux對象能夠被配置在SecurityPolicy對象中,SecurityPolicy對象容許控制Bayeux協議的各個步驟。例如handshake、subscription、publish等
默認狀況下,Bayeux對象沒有被配置到SecurityPolicy,這意味着任何操做都是通過受權的。
SecurityPolicy 有一個默認的實現對象DefaultSecurityPolicy,它可做爲一個基類用於定製安全權限。
SecurityPolicy 的方法有:
boolean canHandshake(BayeuxServer server, ServerSession session, ServerMessage message);
boolean canCreate(BayeuxServer server, ServerSession session, String channelId, ServerMessage message);
boolean canSubscribe(BayeuxServer server, ServerSession session, ServerChannel channel, ServerMessage messsage);
boolean canPublish(BayeuxServer server, ServerSession session, ServerChannel channel, ServerMessage messsage);
DefaultSecurityPolicy 實現了:
1.容許任何handshake
2.容許建立除meta channel以外的任何由客戶端發送通信握手過來的channel。
3.可進行任何由客戶端handshake過來的訂閱,除meta channel以外
4.容許publish 除meta channel
Authorizers(受權者)
Authorizers 實現了Autorizer,並在服務端啓動時添加到channel中。此時channel並未發生任何操做。
Authorizers很是適合用來控制channel在啓動時進行身份認證,或者在運行時創建從新創建ID的channel。
Autorizers不支持meta channel,可是能夠被添加到一個帶有通配符的channel中,並能夠影響全部符合的通配channel。
一個Autorizers添加到/**上,會影響全部的channel。對非通配的,會做用到父級,如:/chat/room/10上添加受權者,也會做用於/chat/room/* /chat/room/** /chat/** /**
=================================
mutiple sessions
=================================
HTTP 協議推薦每一個域最多有兩個connect鏈接。雖然如今瀏覽器默認配置沒兩個域有兩個以上的鏈接,
可是這樣作是不安全的,所以任何的iframe,標籤或者窗口在同一個瀏覽器鏈接到同一主機時須要共享兩個鏈接。
若是兩個iframe/tabs/windows啓動了一個Bayeux通信,都將開始一個長輪詢鏈接請求,而且兩個鏈接都被消耗掉,使得其它的Bayeux請求沒法被傳送,直到其中的長輪詢結束。
================================
服務端 service
================================
CometD服務是一個java類,它容許開發者指定當貝葉消息到達貝葉通道時運行的代碼塊。
消息到達一個已訂閱通道的服務器實例,回調方法將被調用執行用戶特定的代碼。
Cometd 2 服務有兩種:繼承和註解。
1.繼承
Cometd繼承服務實現自org.cometd.server.AbstractService。它指定了服務器感興趣的Bayeux通道,
public class EchoService extends AbstractService //繼承 AbstractService
{
public EchoService(BayeuxServer bayeuxServer)
{
super(bayeuxServer, "echo"); //經過BayeuxServer對象和服務通道名稱調用父類構造
addService("/echo", "processEcho"); //訂閱echo通道, 並指定消息到達通道時的回調函數
}
public void processEcho(ServerSession remote, Map<String, Object> data) //定義回調函數
{
remote.deliver(getServerSession(), "/echo", data, null); //使用ServerSessionAPI將消息返回給特定的客戶端
}
}
這是一個簡單的echo服務,遠程的客戶端經過echo通道將數據返回給遠程的客戶端自己。
BayeuxService須要回調函數至少實現如下方法中的一個:
// 獲取遠程session對象及消息對象
public void processEcho(ServerSession remote, Message message)
//獲取遠程session對象,以及消息對象的Map形式
// 附加的消息信息,例如當通道或id丟失的時候
public void processEcho(ServerSession remote, Map<String, Object> data)
//得到遠程session對象,channel名稱,消息對象,消息id
public void processEcho(ServerSession remote, String channelName, Message message, String messageId)
//得到遠程session對象,channel名稱,消息對象map形式,消息id
public void processEcho(ServerSession remote, String channelName, Map<String, Object> data, String messageId)
既然chanel名稱能夠在subscribe()中指定,而且能夠應用通配,如:
public class BaseballTeamService extends AbstractService
{
public BaseballTeamService(BayeuxServer bayeux)
{
super(bayeux, "baseballTeam");
addService("/baseball/team/*", "processBaseballTeam");
}
public void processBaseballTeam(ServerSession remote, String channelName, Map<String, Object> data, String messageId)
{
// Upon receiving a message on channel /baseball/team/*, forward to channel /events/baseball/team/*
//接收/baseball/team/*的消息,併發布至/events/baseball/team/*通道
getBayeux().getChannel("/events" + channelName).publish(getServerSession(), data, null);
}
}
在示例代碼中,咱們經過調用deliver()方法對一個指定的遠程客戶單發送消息,使用publish方法對訂閱了某一通道的全部客戶端發送消息。
2.註解
從Cometd2.1.0開始支持註解
經過@Service標註的類做爲標註服務,可使用在客戶端和服務端。
-----------------
服務端註解服務
-----------------
服務器端的cometd一般用AbstractServer實現類來實現,這些類的實例一般是一個單例模式,而且在web app配置並在啓動的時候建立。
AbstractServer對可用的服務端功能實現、與serverSession訪問相關聯、使用服務實例註冊、消息回調等功能提供較少的方法。
一個服務可能依賴於其餘的服務,而且可能須要管理生命週期,例如在適當的時候可能須要調用服務的start()或stop()方法。
在繼承AbstractService這種實現方式上,依賴注入和生命週期的管理須要手動在servlet或者監聽者裏面配置。
服務端經過註解方式實現的服務對Cometd產品特色提供了完美的支持。而且有限的支持依賴注入和生命週期管理經過org.cometd.annotation.ServerAnnotationProcessor類。
@@依賴注入支持
Comted工程提供了有限的依賴注入支持,由於這一般經過其餘框架實現,例如spring或guice。
尤爲是,它近支持了注入BayeuxServer對象的fields和methods。而且依賴注入僅在未執行的狀況下執行一次。
如:
@org.cometd.annotation.Service("echoService")//使用@Service註解server類,並指定server名爲「echoService」
public class EchoService
{
@javax.inject.Inject//經過標準的JSR 330註解field
private BayeuxServer bayeux;
}
@Inject注入被聽從JSR330標準的依賴注入容器所支持,如Spring3.x。
@@生命週期管理支持
Cometd 工程經過JSR 250 @PostConstruct and @PreDestroy標準 提供了生命週期管理註解。
這對於那些不適用依賴注入容器來管理生命週期的如spring提供支持。
@@通道配置支持
爲了在chanel被實際訂閱以前初始化,Comted API提供了BayeuxServer.createIfAbsent方法,它能夠經過參數配置給定的channel
此外,在任何訂閱或者監聽者添加以前配置channel這一步驟很是的有用,例如在channel上配置受權人。
在註解服務內,咱們可使用@Configure註解方法,如:
@Service("echoService")
public class EchoService
{
@Inject
private BayeuxServer bayeux;
@Configure("/echo")
public void configure(ConfigurableServerChannel channel)
{
channel.setLazy(true);
channel.addAuthorizer(GrantAuthorizer.GRANT_PUBLISH);
}
}
@@Session 配置支持
繼承AbstractServer的服務有兩個方便反而方法訪問LocalSession和ServerSession,方法名分別是
getLocalSession()和getServerSession()。
@Service("echoService")
public class EchoService
{
@Inject
private BayeuxServer bayeux;
@org.cometd.annotation.Session
private LocalSession localSession;
@org.cometd.annotation.Session
private ServerSession serverSession;
}
@session註解的域是可選的。咱們能夠僅僅使用LocalSession field,或者兩個,或者都不使用。這取決於你是否須要他們。
Session域或者方法不能被@Inject標註。由於LocalSession和ServerSession是有關聯的,而且綁定一個特殊的服務實例。
使用普通的注入機制會致使程序混亂。
@@監聽着配置支持
對服務端來講,使用@Listener註解方法表示回調在服務端處理的消息調用的回調過程。
監聽者消息經過得到SeverSession半對象的引用來發送消息,而且經過ServerMessage對server加工。
@Service("echoService")
public class EchoService
{
@Inject
private BayeuxServer bayeux;
@Session
private ServerSession serverSession;
@org.cometd.annotation.Listener("/echo")
public void echo(ServerSession remote, ServerMessage.Mutable message)
{
String channel = message.getChannel();
Object data = message.getData();
remote.deliver(serverSession, channel, data, null);
}
}
回調函數可能會返回false指明隨後的監聽者不該該被執行而且消息不會被publish
@@支持訂閱配置
對服務端來講,使用@Subscription標註的方法表示本地端處理消息時的回調函數
本地處理等同於遠程客戶端處理,不是服務端本地。
語義很是相似於遠程客戶端的處理,就意義而言,消息在服務端處理完畢後將會被髮布,當它到達另外一端時發佈者將不可用。
所以消息將被載入Message對象中,而非ServerMessage中.
@@註解處理
cometd註解處理類爲ServerAnnotationProcessor
BayeuxServer bayeux = ...;
// Create the ServerAnnotationProcessor
ServerAnnotationProcessor processor = new ServerAnnotationProcessor(bayeux);
// Create the service instance
EchoService service = new EchoService();
// Process the annotated service
processor.process(service);
當process方法返回以後,服務器經過調用初始化生命週期方法以及註冊監聽者和訂閱者已經處理完標註的BayeuxServer對象以及session對象
java
查看更多web