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

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

 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>

2、java类TestComet

里面附上了不少的注释,如果想仔细研究建议看上面的赋予的API文档链接。

package com.zjm.www.test;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.comet4j.core.CometContext;
import org.comet4j.core.CometEngine;

/**
* 描述:服务端主动推送消息到客户端 简单例子
* @author zjm
* @time 2014/8/7
*/
public class TestComet implements ServletContextListener {

// 频道1
private static final String CHANNEL1 = "result1";
// 频道2
private static final String CHANNEL2 = "result2";

// 通过频道1推送给前台的变量1
private static int number1 = 0 ;
// 通过频道2推送给前台的变量2
private static int number2 = 100 ;

/**
* 初始化上下文
*/
public void contextInitialized(ServletContextEvent arg0) {

// CometContext : Comet4J上下文,负责初始化配置、引擎对象、连接器对象、消息缓存等。
CometContext cc = CometContext.getInstance();
// 注册频道,即标识哪些字段可用当成频道,用来作为向前台传送数据的“通道”
cc.registChannel(CHANNEL1);
cc.registChannel(CHANNEL2);

Thread myThread = new Thread(new SendToClientThread(), "SendToClientThread");
// 下面的内部类的方法是个死循环,设置helloAppModule线程为“守护线程”,则当jvm只剩“守护线程”时(主线程结束),该线程也会结束。
myThread.setDaemon(true);
// 开始线程
myThread.start();
}

/**
* 内部类线程类
*/
class SendToClientThread implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
// CometEngine : 引擎,负责管理和维持连接,并能够必要的发送服务
CometEngine engine = CometContext.getInstance().getEngine();
// 参数的意思:通过什么频道(CHANNEL1)发送什么数据(number1++),前台可用可用频道的值(result1)来获取某频道发送的数据
engine.sendToAll(CHANNEL1, number1++);
engine.sendToAll(CHANNEL2, number2++);
}
}
}

public void contextDestroyed(ServletContextEvent arg0) {
}
}

 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 }

3、客户端代码

<!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.js"></script>
<script type="text/javascript">
function init(){

var number1 = document.getElementById(‘number1‘);
var number2 = document.getElementById(‘number2‘);
// 建立连接,conn 即web.xml中 CometServlet的<url-pattern>
JS.Engine.start(‘conn‘);
// 监听后台某个频道
JS.Engine.on(
{
// 对应服务端 “频道1” 的值 result1
result1 : function(num1){
number1.innerHTML = num1;
},
// 对应服务端 “频道2” 的值 result2
result2 : function(num2){
number2.innerHTML = num2;
},
}
);
}
</script>
</head>
<body >
数字1:<span id="number1">...</span><br></br>
数字2:<span id="number2">...</span>
</body>
</html>

 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 >
31         数字1:<span id="number1">...</span><br></br>
32         数字2:<span id="number2">...</span>
33 </body>
34 </html>

 4、网页显示

数字1:2221

数字2:2321 

可以看出,两个数字不停地每秒递增。数字2比数字1 多了100,因为在服务端,number2的初始值为100,number1的初始值为0。

在浏览器上按F12,选择netWork,如下图,可以看出,此连接从未断开过。

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

分类: java_web

时间: 2024-10-12 14:50:42

java 使用 comet4j 主动向客户端推送信息 简单例子的相关文章

pushlet实现服务器端向客户端推送信息

使用Pushlet来实现服务器端向客户端推送信息 1.   实现方式: 有两种实现方式: 1.         通过配置文件来实现定时的从服务器端向客户端推送信息 2.         通过API主动向另外一端推送信息 以下分别给予介绍. 2.   特别注意 在开始测试之前,有三点非常重要,需要实现讲明,否则程序将会无法正常运行: 2.1.     JSP页面上的设定 JSP页面上必须添加以下代码以确保Pushlet能够正确的获得后台服务的地址: <base href="<%=req

5.Android消息推送机制简单例子

1.首先布局文件xml代码: 1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width=&

服务端主动给客户端推送消息

在了解这个之前,先要知道ajax,队列和递归 ajax操作 异步提交,局部刷新.用它就可以实现轮询/长轮询 创建django项目 views from django.shortcuts import render,HttpResponse import json from django.http import JsonResponse # Create your views here. # 验证ajax def ab_dy(request): if request.method == 'post

11.Arduino基础入门— 8.Arduino通过MQTT客户端推送信息

两个库的引用, 其中,PubSubClient可以在Arduino IDE的库管理器中找到: #include <WiFi.h> 本来是#include <ESP8266WiFi.h> 改成Wifi.h即可. #include <WiFi.h> #include <PubSubClient.h> //设置设备ID const String deviceID = "tempDevice1"; // 设置wifi连接用户密码 const ch

Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送

Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送,写这个系列真的很要命,你要去把他们的API文档大致的翻阅一遍,而且各种功能都实现一遍,解决各种bug各种坑,不得不说,极光推送真坑,大家使用还是要慎重,我们看一下极光推送的官网 https://www.jpush.cn/common/ 推送比较使用,很多软件有需要,所以在这个点拿出来多讲讲,我们本节

WebSocket 实现服务端给客户端推送消息

目录 代码发布 应用场景 ajax 操作 队列 递归 如何实现服务端主动给客户端推送消息的效果 长轮询(兼容性好) websocker(主流浏览器都支持) 代码验证(了解) 代码发布 服务端主动给客户端推送消息 截至目前为止,我们所写的 web 项目基本都是基于 HTTP 协议的 HTTP 协议有四大特性:无链接 基于 HTTP 协议实现服务端主动给客户端推送消息好像有点麻烦--- 我们都经历过,浏览器打开一个网站不动,网站过一会儿自动弹出消息 再比如网页版本的微信和 qq,我们所有人创建一个群

java集成jpush实现客户端推送

代码地址如下:http://www.demodashi.com/demo/13700.html 前言 java 集成jpush 实现客户端推送 一.准备工作 开发环境: jdk1.6 Eclipse Luna Service Release 1 (4.4.1) 运行环境: eclipse 二.jpush 推送说明 jpush推送是国内的服务厂商提供的一站式push服务(同时支持iOS.android),后面也加入了即时通讯的能力供app使用.致力于打造简单.可靠.价格有竞争力的服务(简单功能全免

JAVA web实时消息服务器后台推送技术方案---GoEasy

Goeasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送!个人感觉goeasy推送更稳定,推送速度快,代码简单易懂上手快浏览器兼容性:GoEasy推送支持websocket 和polling两种连接方式,从而可以支持IE6及其以上的所有版本,同时还支持其它浏览器诸如Firefox, Chrome, Safari 等等.支 持不同的开发语言:   GoEasy推送提供了Restful API接口,无论你的后台程序用的是哪种语言都可以通过RestfulAPI来实现后台实时推送.

SCCM 2016 向客户端推送Endpoint Protection

说道EndPoint Protect大家也许比较陌生,简单来说,它是微软提供的一套免费的企业级杀毒软件. 大家可能在日常的企业中,可能会用到企业级的瑞星,ESET,卡巴斯基,趋势的OfficeScan等等企业级的管理杀毒软件, 他们方便管理,功能齐全,但是企业级的价格昂贵,且很多软件是按照客户端数量来收费. 说说我们今天介绍的 EndPoint Protection, 他就比较符合咱们中国人的购买需求,什么? 那就是免费,便宜!! 价格才是王道! 就像是Hyper-V上的安装免费的Windows