java 使用 comet4j 主動向客戶端推送信息 簡單例子


【背景】

  今天,一個前端的師弟問我怎樣做實時聊天窗口,我毫不猶豫地說:在前台定時訪問服務端呀!師弟默默地百度了一番,最后告訴我,有一種技術是后服務端動推送信息給客戶端的,這種技術的名字叫comet,我驚呆了,因為完全沒聽過,趕緊上網搜集資料,耗了一個晚上寫了個簡單的例子,實現主動向客戶端發送信息。說是說主動,其實還是要客戶端先獻出它的“第一次”,即只要它有先請求你一下,以后你們熟了,你想主動約它就約它!

  關於comet技術介紹及其實現原理,可以參考網站 http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 的介紹。

  簡單來說,就是客戶端發送請求到服務端,服務器端會阻塞請求直到有數據傳遞或超時才返回,之后客戶端 JavaScript 響應處理函數會在處理完服務器返回的信息后,再次發出請求,重新建立連接。當客戶端處理接收的數據、重新建立連接時,服務器端可能有新的數據到達;這些信息會被服務器端保存直到客戶端重新建立連接,客戶端會一次把當前服務器端所有的信息取回。  

 

【工作環境】

1、myeclipse2013

2、tomcat 6.0

3、jdk 7

4、火狐瀏覽器

說明 

測試成功的瀏覽器有:(1)火狐瀏覽器  (2)IE10、IE9、IE8  (3)360極速瀏覽器極速模式

測試失敗的瀏覽器有:(1)IE10兼容模式、IE7

  

【准備工作】

1、下載comet4j.js  :http://files.cnblogs.com/xiaoMzjm/comet4j.js.rar

2、下載comet4j-tomcat6.jar  :http://files.cnblogs.com/xiaoMzjm/comet4j-tomcat6.jar.rar

3、到tomcat目錄下——conf——server.xml 下,把

    <Connector 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"
/>  

說明: 

其實那個js文件和jar官網是https://code.google.com/p/comet4j/ 的,但它是谷歌,這里是天朝吶,所以貼了兩個我文件夾里面的包的地址上來。    

comet4j-tomcat6.jar 還有另一個版本是 comet4j-tomcat7.jar , 自己選擇合適的版本去下載。6以下的tomcat肯定不行就對了。

comet4j.js 的官方使用文檔: http://doc.comet4j.tk/jsdocs/

comet4j-tomcat6.jar 的官方使用文檔:   http://doc.comet4j.tk/apidocs/

  

【新建項目過程】

(1)新建服務端的類TestComet , 實現  ServletContextListener  接口

(2)在web.xml 里面應該配置 攔截器:

    <listener>
        <listener-class>org.comet4j.core.CometAppListener</listener-class>
    </listener>
    <listener>
        <description>HelloWorld</description>
        <listener-class>com.zjm.www.test.TestComet</listener-class>
    </listener>
    <servlet>
        <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-tomcat6.jar下的一個servlet:org.comet4j.core.CometServlet , 客戶端訪問的入口

另一個是comet4j-tomcat6.jar下的監聽器:org.comet4j.core.CometAppListener , 監聽我們自己的類。

 

【具體代碼(說明都寫在注釋里面)】

1、web.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" 
 3     xmlns="http://java.sun.com/xml/ns/javaee" 
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 7     <listener>
 8         <listener-class>org.comet4j.core.CometAppListener</listener-class>
 9     </listener>
10     <listener>
11         <description>HelloWorld</description>
12         <listener-class>com.zjm.www.test.TestComet</listener-class>
13     </listener>
14     <servlet>
15         <display-name>CometServlet</display-name>
16         <servlet-name>CometServlet</servlet-name>
17         <servlet-class>org.comet4j.core.CometServlet</servlet-class>
18     </servlet>
19     <servlet-mapping>
20         <servlet-name>CometServlet</servlet-name>
21         <url-pattern>/conn</url-pattern>
22     </servlet-mapping>
23 
24     
25   <welcome-file-list>
26     <welcome-file>index.jsp</welcome-file>
27   </welcome-file-list>
28 </web-app>
View Code

 

2、java類TestComet

里面附上了不少的注釋,如果想仔細研究建議看上面的賦予的API文檔鏈接。

 1 package com.zjm.www.test;
 2 
 3 import javax.servlet.ServletContextEvent;
 4 import javax.servlet.ServletContextListener;
 5 
 6 import org.comet4j.core.CometContext;
 7 import org.comet4j.core.CometEngine;
 8 
 9 /**
10  * 描述:服務端主動推送消息到客戶端  簡單例子
11  * @author zjm
12  * @time 2014/8/7
13  */
14 public class TestComet implements ServletContextListener {
15     
16         // 頻道1
17         private static final String CHANNEL1 = "result1";
18         // 頻道2
19         private static final String CHANNEL2 = "result2";
20         
21         // 通過頻道1推送給前台的變量1
22         private static int number1 = 0 ;
23         // 通過頻道2推送給前台的變量2
24         private static int number2 = 100 ;
25         
26         /**
27          * 初始化上下文
28          */
29         public void contextInitialized(ServletContextEvent arg0) {
30             
31                 // CometContext : Comet4J上下文,負責初始化配置、引擎對象、連接器對象、消息緩存等。
32                 CometContext cc = CometContext.getInstance();
33                 // 注冊頻道,即標識哪些字段可用當成頻道,用來作為向前台傳送數據的“通道”
34                 cc.registChannel(CHANNEL1);
35                 cc.registChannel(CHANNEL2);
36                 
37                 Thread myThread = new Thread(new SendToClientThread(), "SendToClientThread");
38                 // 下面的內部類的方法是個死循環,設置helloAppModule線程為“守護線程”,則當jvm只剩“守護線程”時(主線程結束),該線程也會結束。
39                 myThread.setDaemon(true);
40                 // 開始線程
41                 myThread.start();
42         }
43 
44         /**
45          * 內部類線程類
46          */
47         class SendToClientThread implements Runnable {
48                 public void run() {
49                         while (true) {
50                                 try {
51                                         Thread.sleep(1000);
52                                 } catch (Exception ex) {
53                                         ex.printStackTrace();
54                                 }
55                                 // CometEngine : 引擎,負責管理和維持連接,並能夠必要的發送服務
56                                 CometEngine engine = CometContext.getInstance().getEngine();
57                                 // 參數的意思:通過什么頻道(CHANNEL1)發送什么數據(number1++),前台可用可用頻道的值(result1)來獲取某頻道發送的數據
58                                 engine.sendToAll(CHANNEL1, number1++);
59                                 engine.sendToAll(CHANNEL2, number2++);
60                         }
61                 }
62         }
63 
64         public void contextDestroyed(ServletContextEvent arg0) {
65         }
66 }
View Code

 

3、客戶端代碼

 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5 <title>Comet4J Hello World</title>
 6 <script type="text/javascript" src="js/comet4j.js"></script>
 7 <script type="text/javascript">
 8 function init(){
 9     
10         var number1 = document.getElementById('number1');
11         var number2 = document.getElementById('number2');
12         // 建立連接,conn 即web.xml中 CometServlet的<url-pattern>
13         JS.Engine.start('conn');
14         // 監聽后台某個頻道
15         JS.Engine.on(
16                { 
17                    // 對應服務端 “頻道1” 的值 result1
18                    result1 : function(num1){
19                        number1.innerHTML = num1;
20                 },
21                 // 對應服務端 “頻道2” 的值 result2
22                 result2 : function(num2){
23                        number2.innerHTML = num2;
24                 },
25             }
26            );
27 }
28 </script>
29 </head>
30 <body onload="init()">
31         數字1:<span id="number1">...</span><br></br>
32         數字2:<span id="number2">...</span>
33 </body>
34 </html>
View Code

 

 4、網頁顯示

數字1:2221

數字2:2321 

可以看出,兩個數字不停地每秒遞增。數字2比數字1 多了100,因為在服務端,number2的初始值為100,number1的初始值為0。

在瀏覽器上按F12,選擇netWork,如下圖,可以看出,此連接從未斷開過。

 有什么寫錯或寫得不好的地方,歡迎大家提出來~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM