生活随笔
收集整理的這篇文章主要介紹了
利用Comet4J 及时推送消息
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? 簡介
Comet4J是一個微型的即時推送框架,它分為服務端與客戶端兩部分,你只要將服務器端(JAR文件,目前僅支持Tomcat6、7)放入WEB-INF\lib,客戶端(JavaScript文件)引入到頁面,那么你的應用就具備了向客戶端推送信息的能力,而你僅需要在服務器端調用Comet4J所提供發送方法,信息就會被主動的推送到客戶的瀏覽器上。
?
準備工作
?
?
下載服務端jar文件
?
Comet4J目前僅支持Tomcat6、7版本,根據您所使用的Tomcat版本下載【comet4jtomcat6.jar】或【comet4j-tomcat7.jar】文件放置到WEB項目的WEB-INF\lib目錄下。
?
下載客戶端js文件
下載【comet4j.js】到您的項目中,比如:WebContent\js目錄下。
?
?
修改服務器配置文件
因為Comet4J工作在NIO方式下,所以我們需要調整服務器連接器配置,更換為NOI連接器。 打開server.xml文件將找到原先的連接器配置:
[html]?view plaincopy
<Connector?executor="tomcatThreadPool"?port="8080"?protocol="HTTP/1.1"?connectionTimeout="20000"?redirectPort="8443"?/>??
替換為:
[html]?view plaincopy
<Connector?URIEncoding="UTF-8"?connectionTimeout="20000"?port="8080"?protocol="org.apache.coyote.http11.Http11NioProtocol"?redirectPort="8443"/>??
?
客戶端
我們利用Comet4J開發一個每隔一秒向所有客戶端推送服務器的剩余內存大小。 helloworld.html
?
[html]?view plaincopy
<!DOCTYPE?html?PUBLIC?"-//W3C//DTD?XHTML?1.0?Transitional//EN"?"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">??<html?xmlns="http://www.w3.org/1999/xhtml">??<head>??<meta?http-equiv="Content-Type"?content="text/html;?charset=utf-8"?/>??<title>Comet4J?Hello?World</title>??<script?type="text/javascript"?src="js/comet4j-0.0.2.js"></script>??<script?type="text/javascript">??function?init(){??????????var?kbDom?=?document.getElementById('kb');??????????JS.Engine.on({??????????????????hello?:?function(kb){//偵聽一個channel??????????????????????????kbDom.innerHTML?=?kb;??????????????????}??????????});??????????JS.Engine.start('conn');??}??</script>??</head>??<body?onload="init()">??????????剩余內存:<span?id="kb">...</span>KB??</body>??</html>??
?
?
服務端
helloworld.java
?
?
?
[java]?view plaincopy
package?org.comet4j.demo.helloworld;????import?javax.servlet.ServletContextEvent;??import?javax.servlet.ServletContextListener;????import?org.comet4j.core.CometContext;??import?org.comet4j.core.CometEngine;????public?class?HelloWorld?implements?ServletContextListener?{??????????private?static?final?String?CHANNEL?=?"hello";??????????public?void?contextInitialized(ServletContextEvent?arg0)?{??????????????????CometContext?cc?=?CometContext.getInstance();??????????????????cc.registChannel(CHANNEL);//注冊應用的channel??????????????????Thread?helloAppModule?=?new?Thread(new?HelloAppModule(),?"Sender?App?Module");??????????????????helloAppModule.setDaemon(true);??????????????????helloAppModule.start();????????????}????????????class?HelloAppModule?implements?Runnable?{??????????????????public?void?run()?{??????????????????????????while?(true)?{??????????????????????????????????try?{??????????????????????????????????????????Thread.sleep(1000);??????????????????????????????????}?catch?(Exception?ex)?{??????????????????????????????????????????ex.printStackTrace();??????????????????????????????????}??????????????????????????????????CometEngine?engine?=?CometContext.getInstance().getEngine();??????????????????????????????????engine.sendToAll(CHANNEL,?Runtime.getRuntime().freeMemory()/1024);??????????????????????????}??????????????????}??????????}????????????public?void?contextDestroyed(ServletContextEvent?arg0)?{????????????}??}??
?
?
配置
web.xml
[html]?view plaincopy
<listener>??????????????????<description>Comet4J容器偵聽</description>??????????????????<listener-class>org.comet4j.core.CometAppListener</listener-class>??????????</listener>??????????<servlet>??????????????????<description>Comet連接[默認:org.comet4j.core.CometServlet]</description>??????????????????<display-name>CometServlet</display-name>??????????????????<servlet-name>CometServlet</servlet-name>??????????????????<servlet-class>org.comet4j.core.CometServlet</servlet-class>??????????</servlet>??????????<servlet-mapping>??????????????????<servlet-name>CometServlet</servlet-name>??????????????????<url-pattern>/conn</url-pattern>??????????</servlet-mapping>????<listener>????<description>HelloWorld</description>????<listener-class>org.comet4j.demo.helloworld.HelloWorld</listener-class>??</listener>??
?
客戶端使用簡介
?
客戶端是一個JavaScript文件(comet4j-0.0.2.js),其中最重要的是JS.Connector和JS.Engine兩個類。JS.Connector負責與服務器建立并保持連接,而JS.Engine類負責將服務器推送過來的消息轉化為開發人員可以處理的消息事件,并分發出去,大多數情況下,我們僅需要使用JS.Engine類就可以完成多數的開發工作。
JS.Engine類是一個靜態類,在一個頁面中只有一個JS.Engine類的實例。它除了負責把服務器推過來的消息轉化為事件分發以外,與服務器的連接與斷開也由此類負責。
JS.Engine.start方法
JS.Engine.start(String str)和JS.Engine.stop(String str)分別控制連接和斷開動作,start方法需要傳入一個字符串參數,用來指定您配置的Comet4J連接地址。比如按前面準備工作的配置了CometServlet的地址為/conn,那么可以這樣寫:
[javascript]?view plaincopy
JS.Engine.start('/conn');??
上段代碼我們讓瀏覽器與服務器進行連接,當連接成功以后JS.Engine類會發出"start"事件,如何進行事件的處理我們稍后介紹。
JS.Engine.stop方法
我們也能夠讓連接斷開:
[javascript]?view plaincopy
JS.Engine.stop('主動斷開');??
上面代碼我們讓連接斷開,并傳入了一個“主動斷開”這樣一個斷開的原因。如果您并不需要對斷開的原因進行說明,也可以不傳遞參數:
[javascript]?view plaincopy
JS.Engine.stop();??
JS.Engine類的事件處理
上面我們介紹了如何使用start和stop方法來建立和斷開連接,當成功建立連接已后JS.Engine會發出"start"事件,當斷開后會發出“stop”事件,當收到某個通道推送過來的信息時也會發出與通道標識同名的事件。您可以事先在中使用JS.Engine.on方法來注冊事件處理函數。例如:
[javascript]?view plaincopy
JS.Engine.on('start',function(cId,?channelList,?engine){??????alert('連接已建立,連接ID為:'?+?cId);??});??JS.Engine.on('stop',function(cause,?cId,?url,?engine){??????alert('連接已斷開,連接ID為:'?+?cId?+?',斷開原因:'?+?cause?+?',斷開的連接地址:'+?url);??});??
也可以將上段代碼寫成,下面代碼與上段代碼完全等效:
[javascript]?view plaincopy
JS.Engine.on({??????start?:?function(cId,?channelList,?engine){????????alert('連接已建立,連接ID為:'?+?cId);??????},??????stop?:?function(cause,?cId,?url,?engine){????????alert('連接已斷開,連接ID為:'?+?cId?+?',斷開原因:'?+?cause?+?',斷開的連接地址:'+?url);??????}??});??
?
接下來,介紹一下如何對服務器推送過來的消息進行處理。在介紹之前,我們假設后臺已經注冊了一個"hello"的應用通道標識,并且只向客戶端推送簡單的字符串信息。先看如下代碼:
[javascript]?view plaincopy
JS.Engine.on('hello',function(text){??????alert(text);??});??
這樣當服務器端使用"hello"通道標識推送過來的消息就可以由上段代碼進行處理,將推送過來的信息彈出。
特別注意:以上代碼在事件處理函數中使用了alert僅為說明函數功能,實際使用中,在事件處理函數中切勿使用alert、prompt、confirm等可以中斷腳本運行的函數,因為Engine需要實時的保持工作狀態。
?
服務器端使用簡介
服務端由一個Jar包組成,其中最重的是CometContext和CometEngine兩個類。
Comet Context 類
CometContext是一個單態類,通過其getInstance方法來獲得實例,它主要負責框架的一些初始化工作保存著一些參數的配置值,除此之外它還有一個更重要的職責——負責注冊應用通道標識。如果您想使用框架來實現自己的應用,那么您必需要為自己的應用分配一個唯一的通道標識,并將此通道標識在WEB容器啟動時使用CometContext的registChannel方法進行注冊,這樣,客戶端才可以正確接受此應用所推送的消息。注冊一個通道標識非常簡單
[java]?view plaincopy
CometContext.getInstance().registChannel("hello");??
這樣便注冊了一個標識為“hello”的應用通道,而客戶也可以通過JS.Engine.on('hello',function(msg){...})的形式來接收并處理來自此通道的消息。
Comet Engine 類
另一個重要的類是CometEngine,它除了負責對連接的處理之外,對于開發人員而言,更加常用的可能是它所提供的sendTo或sendToAll方法來向客戶端發送消息:
[java]?view plaincopy
ring?channel?=?"hello";??String?someConnectionId?=?"1125-6634-888";??engine.sendToAll(channel?,?"我來了!");??engine.sendTo(channel?,?engine.getConnection(someConnectionId),“Hi,我是XXX”);??
上面代碼使用sendToAll方法向所有客戶端在"hello"通道上發送了“我來了!”這樣一條消息,然后又使用sendTo在同樣的通道上向某一個連接發送了“Hi,我是XXX”消息。 CometEngine另外一個很重要的地方在于,它是框架工作的事件引擎的集散地,它提供了BeforeConnectEvent、BeforeDropEvent、ConnectEvent、DropEvent、MessageEvent等事件。通過對這些事件的處理來實現具體的功能:
[java]?view plaincopy
class?JoinListener?extends?ConnectListener?{??????????@Override??????????public?boolean?handleEvent(ConnectEvent?anEvent)?{??????????????????CometConnection?conn?=?anEvent.getConn();??????????????????CometContext.getInstance().getEngine().sendTo("hello",?conn.getId(),"歡迎上線");??????????}??}????CometEngine?engine?=?CometContext.getInstance().getEngine();??engine.addConnectListener(new?JoinListener()??
上面先定義了一個JoinListener并實現了父類ConnectListener的handleEvent抽像方法,然后使用engine.addConnectListener來注冊這個事件偵聽。這樣,在有客戶與服務器成功建立連接已后,就可以向此客戶端推送一條歡迎信息。
Comet4J配置參數表
[html]?view plaincopy
<!--Comet4J配置?-->??<listener>??????????<description>Comet4J容器偵聽</description>??????????<listener-class>org.comet4j.core.CometAppListener</listener-class>??</listener>??<servlet>??????????<description>Comet連接[默認:org.comet4j.core.CometServlet]</description>??????????<display-name>CometServlet</display-name>??????????<servlet-name>CometServlet</servlet-name>??????????<servlet-class>org.comet4j.core.CometServlet</servlet-class>??</servlet>??<servlet-mapping>??????????<servlet-name>CometServlet</servlet-name>??????????<url-pattern>/conn</url-pattern>??</servlet-mapping>??<!--?Comet4J可選參數配置-->??<context-param>??????????<description>語言[支持:zh,en,默認:zh,詳細http://www.loc.gov/standards/iso639-2/php/English_list.php]</description>??????????<param-name>Comet.Language</param-name>??????????<param-value>zh</param-value>??</context-param>??<context-param>??????????<description>請求超時時間/微妙[默認:60000,1分鐘,建議至少設置3秒以上]</description>??????????<param-name>Comet.Timeout</param-name>??????????<param-value>60000</param-value>??</context-param>??<context-param>??????????<description>連接空閑過期時間/微妙[默認:5000,5秒]</description>??????????<param-name>Comet.ConnExpires</param-name>??????????<param-value>5000</param-value>??</context-param>??<context-param>??????????<description>連接檢查頻率/微妙[默認:5000,5秒]</description>??????????<param-name>Comet.ConnFrequency</param-name>??????????<param-value>5000</param-value>??</context-param>??<context-param>??????????<description>緩存信息過期時間/微妙[默認:60000,1分種]</description>??????????<param-name>Comet.CacheExpires</param-name>??????????<param-value>60000</param-value>??</context-param>??<context-param>??????????<description>緩存信息過期檢查頻率/微妙[默認:60000,1分種]</description>??????????<param-name>Comet.CacheFrequency</param-name>??????????<param-value>60000</param-value>??</context-param>??<context-param>??????????<description>連接模式[auto(默認)/stream/lpool]</description>??????????<param-name>Comet.WorkStyle</param-name>??????????<param-value>auto</param-value>??</context-param>??<context-param>??????????<description>開啟調試[false(默認)/true]</description>??????????<param-name>Comet.Debug</param-name>??????????<param-value>false</param-value>??</context-param>??
?
?
?
總結
以上是生活随笔為你收集整理的利用Comet4J 及时推送消息的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。