准備工作
整個例子的源碼下載:http://pan.baidu.com/s/1gfFYSbp
Comet4J目前僅支持Tomcat6、7版本,根據您所使用的Tomcat版本下載【comet4jtomcat6.jar】或【comet4j-tomcat7.jar】文件放置到WEB項目的WEB-INF\lib目錄下。
本文下載comet4j-tomcat7.jar, 下載地址:http://pan.baidu.com/s/1eSBXmfS
下載客戶端js文件
修改服務器配置文件
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
替換為
<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>
客戶端
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Cometd首頁</title> <script type="text/javascript" src="./JS/cometd/comet4j.js"></script> <script type="text/javascript"> var projectPath = '<%= request.getContextPath()%>'; function cometdCallback(text){ var kbDom = document.getElementById('num1'); kbDom.innerHTML = text; } function init() { JS.Engine.on({ number : cometdCallback }); JS.Engine.start(projectPath+'/conn'); } </script> </head> <body onload="init()"> 數字3: <span id="num1">...</span> </body> </html>
其中,<%=request.getContextPath()%>是為了解決相對路徑的問題,可返回站點的根路徑。
服務端
package com.cvicse.ump.cometd; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.comet4j.core.CometContext; public class CometdTestClass implements ServletContextListener { private static final String CHANNEL_NUM = "number"; private static int number = 0; @Override public void contextDestroyed(ServletContextEvent arg0) { } @Override public void contextInitialized(ServletContextEvent arg0) { CometContext.getInstance().registChannel(CHANNEL_NUM); Thread timeThread = new Thread(new TimeThread(),"numTimeThread"); timeThread.setDaemon(true);//設置為守護線程 timeThread.start(); } class TimeThread implements Runnable{ @Override public void run() { while(true){ CometContext.getInstance().getEngine().sendToAll(CHANNEL_NUM, number++); System.out.println(CHANNEL_NUM+": "+number); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>cometd</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <listener> <description>Comet4J容器偵聽</description> <listener-class>org.comet4j.core.CometAppListener</listener-class> </listener> <listener> <listener-class>com.cvicse.ump.cometd.CometdTestClass</listener-class> </listener> <servlet> <description>Comet連接[默認:org.comet4j.core.CometServlet]</description> <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> </web-app>
客戶端使用簡介
客戶端是一個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,那么可以這樣寫:
JS.Engine.start('/conn');
JS.Engine.stop('主動斷開');
上面代碼我們讓連接斷開,並傳入了一個“主動斷開”這樣一個斷開的原因。如果您並不需要對斷開的原因進行說明,也可以不傳遞參數:
JS.Engine.stop();
JS.Engine類的事件處理
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); });
也可以將上段代碼寫成,下面代碼與上段代碼完全等效:
JS.Engine.on({ start : function(cId, channelList, engine){ alert('連接已建立,連接ID為:' + cId); }, stop : function(cause, cId, url, engine){ alert('連接已斷開,連接ID為:' + cId + ',斷開原因:' + cause + ',斷開的連接地址:'+ url); } });
接下來,介紹一下如何對服務器推送過來的消息進行處理。在介紹之前,我們假設后台已經注冊了一個"hello"的應用通道標識,並且只向客戶端推送簡單的字符串信息。先看如下代碼:
JS.Engine.on('hello',function(text){ alert(text); });
CometContext.getInstance().registChannel("hello");
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等事件。通過對這些事件的處理來實現具體的功能:
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()
Comet4J配置參數表
<!--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>