最近工作原因,需要研究客户端推技术,客户端推有3种方式,HTTP streaming、LONG POLLING以及ajax轮询。
ajax轮询:ajax轮询只是感官的推,是通过客户端不断请求响应实现。
HTTP streaming:客户端与服务端建立连接,当服务端收到请求时,往客户端推送消息,此时客户端状态为3即reading状态,非4完成。
LONG POLLING:即长轮询,客户端与服务端建立连接,当服务端收到请求时,往客户端推送消息,此时客户端状态为4即完成,客户端处理消息后,再往服务端发送请求。
首先,什么cometd?使用ajax作为web应用的服务器推技术称为"Comet",cometd是一个提供多种开发语言的Bayeux项目,由dojo项目基金会支持。Bayeux是一种在客户端和服务端之间传输的消息协议(基于HTTP),cometd的消息都是基于Bayeux协议。
cometd作为客户端推技术使用LONG POLLING方式,该技术核心为continuation+beyeux+jquery-cometAPI,
continuation:即servlet服务端端多线程技术,在发起request请求后,HttpServlet对象不会阻塞,而是新开启一个线程等待事件被触发,当事件到来时再进行响应
Beyeux: 支持使用ajax的客户端与服务器端之间灵敏、快速的信息交互。类似于jms订阅机制。
jquery-cometdAPI:封装了cometd客户端的api
好了,废号少说,开发我们的cometd之旅
一、安装demo
1.下载java1.5以上版本,tomcat6以上,安装、配置环境变量。。。。。不用多说吧
2.下载cometd-demo,我用的是6.1.26版本,http://dist.codehaus.org/jetty/jetty-6.1.26/
注意:如果没有使用servlet3.0,请不要到cometd官网下载,而是到jetty官网下载,否则下载demo不能正常运行
3.jetty-6.1.26.zip解压,找到jetty-6.1.26\webapps\cometd.war包,将该war放到tomcat的webapps下面
4.运行demo,启动tomcat后,登录到http://127.0.0.1:8080/cometd/,选择jquery中的chat & XD,进入到聊天室界面。你可以同时打开几个窗口进行聊天了。
现在demo运行成功,直观的感觉有了,下一步,我们继续深入学习代码部分。
二、研究demo中的有效信息
解压war包,删除暂时不需要的东东,保留红圈的部分(使用jquery作为例子讲解)。下图是目录结构(注意:此处是翻译后导入到eclipse的工程结构,怎么导不用多说了吧)
1.先查看web.xml,通过此项配置,我们可以看到,通过cometd/*的请求是由cometd自带api的servlet进行处理,换句说说,聊天信息的提交和发布非自行编写而是统一进行处理。先不要急,后面会慢慢讲到,包括初始化的servlet-CometdDemoServlet。
<context-param> <param-name>org.mortbay.jetty.servlet.ManagedAttributes</param-name> <param-value>org.cometd.bayeux,dojox.cometd.bayeux</param-value> </context-param> <servlet> <servlet-name>cometd</servlet-name> <servlet-class>org.mortbay.cometd.continuation.ContinuationCometdServlet</servlet-class> <init-param> <param-name>filters</param-name> <param-value>/WEB-INF/filters.json</param-value> </init-param> <init-param> <param-name>timeout</param-name> <param-value>120000</param-value> </init-param> <init-param> <param-name>interval</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>maxInterval</param-name> <param-value>10000</param-value> </init-param> <init-param> <param-name>maxLazyLatency</param-name> <param-value>5000</param-value> </init-param> <init-param> <param-name>multiFrameInterval</param-name> <param-value>2000</param-value> </init-param> <init-param> <param-name>logLevel</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>jsonDebug</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cometd</servlet-name> <url-pattern>/cometd/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>cometdDemo</servlet-name> <servlet-class>org.cometd.demo.CometdDemoServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet>
2.再查看jquery-examples\chat\chat.js,找到join方法,这下稍微清楚一点了吧。
首先配置URL请求,再建立握手,此时准备工作已经做好了,再看看下一段代码
this.join = function(username) { //省去一部分.... //生成url,正好的web.xml配置的servlet var cometdURL = location.protocol + "//" + location.host + config.contextPath + "/cometd"; //省去一部分.... //配置URL $.cometd.configure({ url: cometdURL, logLevel: 'debug' }); //建立握手 $.cometd.handshake(); //省去一部分.... };
订阅主题的方法,此方法的功能是:订阅名称为/chat/demo的主题,当该主题产生消息时,调用receive方法
function _subscribe() { //订阅主题,并制定回调方法 _chatSubscription = $.cometd.subscribe('/chat/demo', _self.receive); _membersSubscription = $.cometd.subscribe('/chat/members', _self.members); }
receive回调方法,message可以为text或者json格式
this.receive = function(message) { /* 接收参数 */ var fromUser = message.data.user; var membership = message.data.membership; var text = message.data.chat; /* 执行下一步操作*/ //...省略 chat.append('<span class=\"membership\"><span class=\"from\">' + fromUser + ' </span><span class=\"text\">' + text + '</span></span><br/>'); _lastUser = null; //...省略 };
再看看发送消息的方法吧,找到