首页 > 代码库 > java 使用 comet4j 主动向客户端推送信息 简单例子

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 zjm12  * @time 2014/8/713  */14 public class TestComet implements ServletContextListener {15     16         // 频道117         private static final String CHANNEL1 = "result1";18         // 频道219         private static final String CHANNEL2 = "result2";20         21         // 通过频道1推送给前台的变量122         private static int number1 = 0 ;23         // 通过频道2推送给前台的变量224         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” 的值 result118                    result1 : function(num1){19                        number1.innerHTML = num1;20                 },21                 // 对应服务端 “频道2” 的值 result222                 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,如下图,可以看出,此连接从未断开过。

 有什么写错或写得不好的地方,欢迎大家提出来~