自动采集推送(一个前端师弟问我怎样做实时聊天窗口,我惊呆了)
优采云 发布时间: 2021-11-02 11:01自动采集推送(一个前端师弟问我怎样做实时聊天窗口,我惊呆了)
【背景】
今天有个前端小辈问我如何制作实时聊天窗口。我毫不犹豫的说:前台定期访问服务器!小弟默默百度,最后告诉我有一种技术,就是post-server推送信息给客户端。这项技术的名称是彗星。我愣住了,因为我从来没有听说过,所以我赶紧上网搜集资料。花了一个晚上,写了一个简单的例子,主动向客户端发送信息。说是主动,但实际上,客户必须先给它“第一次”,也就是只要先问你,你以后就熟悉了,如果你想拿主动问吧,请教吧!
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:
2、下载comet4j-tomcat6.jar:
3、 进入到tomcat目录——conf——server.xml,并把
变成:
阐明:
其实js文件和jar官网是对的,不过是谷歌,这里是天朝,所以我把两个包的地址贴在我的文件夹里。
Comet4j-tomcat6.jar 还有一个版本,comet4j-tomcat7.jar,选择合适的版本下载。6以下的Tomcat肯定不行。
Comet4j.js 的官方文档:
Comet4j-tomcat6.jar的官方文档:
【新建项目流程】
(1) 新增服务端类 TestComet,实现 ServletContextListener 接口
(2)*敏*感*词*应该在web.xml中配置:
org.comet4j.core.CometAppListener
HelloWorld
com.zjm.www.test.TestComet
CometServlet
CometServlet
org.comet4j.core.CometServlet
CometServlet
/conn
注意:有两个地方需要配置
一个是comet4j-tomcat6.jar下的servlet:et4j.core.CometServlet,客户端入口
另一个是comet4j-tomcat6.jar下的*敏*感*词*器:et4j.core.CometAppListener,它*敏*感*词*我们自己的类。
【具体代码(说明写在注释中)】
1、web.xml
1
2
7
8 org.comet4j.core.CometAppListener
9
10
11 HelloWorld
12 com.zjm.www.test.TestComet
13
14
15 CometServlet
16 CometServlet
17 org.comet4j.core.CometServlet
18
19
20 CometServlet
21 /conn
22
23
24
25
26 index.jsp
27
28
查看代码
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 }
查看代码
3、客户端代码
1 DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
3
4
5 Comet4J Hello World
6
7
8 function init(){
9
10 var number1 = document.getElementById('number1');
11 var number2 = document.getElementById('number2');
12 // 建立连接,conn 即web.xml中 CometServlet的
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
29
30
31 数字1:...
32 数字2:...
33
34
查看代码
4、网页展示
数字1:2221
数字2:2321
可以看出,这两个数字每秒都在不断增加。数字2比数字1多100,因为在服务器上,number2的初始值为100,number1的初始值为0。
在浏览器上按F12,选择网络,如下图,可以看到这个连接一直没有断开。
写的不好或者写的不好,欢迎大家提出~