java comet_用java实现comet,基于 HTTP长连接的实现,用于从服务端实时发送信息到客户端...
http://homelink.javaeye.com/blog/293328#comments
參考文檔 http://www.ibm.com/developerworks/cn/web/wa-lo-comet/
comet是HTTP長連接,就是在HTTP發送請求時,服務器不立刻發送響應信息給客戶端,
而是保持著連接,等待一定情況發生后才把數據發送回去給客戶端。所以用comet可以實現服務器端的數據實時地發送給客戶端。
本文主要是用java和js來簡單地實現comet,最后附上源碼和使用例子。
在客戶端用XMLRequest發送請求到服務器,在服務器端用一個servlet來接收XMLRequest的請求,當接收到請
求時,并不立刻響應客戶端,而是把該servlet線程阻塞,等到一定事件發生后,再響應客戶端。當客戶端接收到服務端的響應后,調用自定義的回調函數來
處理服務器發送回來的數據,處理完成后,再發送一個XMLRequest請求到服務端,這樣循環下去,就可以實現數據的實時更新,又不必要在客戶端不斷地
輪循(polling)。
利用該comet的實現(以后簡稱為keeper)時,只要在客戶端注冊事件和寫一個處理返回數據的回調函數,然后在服務端實現
keeper中的EventListener接口,調用Controller.action(eventListener,eventType)就可以
了。
keeper分成兩大部分,第一部分為客戶端的javascript,第二部分是服務端的servlet和事件處理。
一.客戶端
建立一個XMLRequest對象池,每發送一次請求,從對象池中取一個XMLRequest對象,如果沒有可用的對象,則創建一
個,把它加入到對象池中。這部分的代碼來自于網絡。
為了使用方便,再添加一些方法,用來注冊事件。這樣只要調用注冊函數來注冊事件,并且把回調函數傳給注冊事件函數就行了,處理數據
的事情,交給回調函數,并由用戶來實現。
keeper為了方便使用,把客戶端的javascript代碼集成在servlet中,當配置好keeper的servlet,
啟動HTTP服務器時,keeper會根據用戶的配置,在相應的目錄下生成客戶端的javascript代碼。
二.服務端
服務端的servlet初始化時,根據配置來生成相應的客戶端javascript代碼。
servlet的入口由keeper.servlet.Keeper.java中的doGet進入。在Keeper的doGet
中,從請求中獲取用戶注冊事件的名稱(字符串類型),然后根據事件的名稱,構造一個事件(Event類型),再把它注冊到NameRegister中,注
冊完成后,該servlet線程調用wait(),把自已停止。等待該servlet線程被喚醒后,從Event中調用事件的EventListener
接口的process(request,response)來處理客戶端的請求。
protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
String?eventName?=?request.getParameter("event");
NameRegister?reg?=?NameRegister.getInstance();
Event?event?=?null;
try?{
event?=?reg.getEvent(eventName);
if(event?==?null)?{
event?=?new?Event(eventName,this);
reg.registeEvent(eventName,?event);
}
if(event.getServlet()?==?null)?{
event.setServlet(this);
}
}?catch?(RegistException?e1)?{
e1.printStackTrace();
}
synchronized(this)?{
while(!event.isProcess())?{
try?{
wait();
}?catch?(InterruptedException?e)?{
e.printStackTrace();
}
}
}
EventListener?listener?=?event.getListener();
if(listener?!=?null)?{
listener.process(request,response);
}
}
在服務端處理事件時,調用了keeper.control.Controller中的靜態方法
action(EventListener listener,String eventName)來處理。如下所示。
public?static?boolean?action(EventListener?listener,String?eventName){
NameRegister?reg?=?NameRegister.getInstance();
HttpServlet?servlet?=?null;
Event?e?=?null;
try?{
e?=?reg.getEvent(eventName,true);
if(e?==?null)?{
return?false;
}
e.setListener(listener);
servlet?=?e.getServlet();
e.setProcess(true);
synchronized(servlet)?{
servlet.notifyAll();
}
}?catch?(RegistException?ex)?{
ex.printStackTrace();
}
if(servlet?!=?null?&&?e?!=?null)?{
e?=?null;
return?true;
}?else?{
return?false;
}
}
下面開始用keeper來寫一個簡單的網頁聊天程序和基于服務端的時間。
1.客戶端設置
注冊兩個事件,一個用于是時間事件,一個是消息事件。同時還要寫兩個回調函數,用于處理服務
端返回的時間和聊天消息。如下所于:
Keeper.addListener('timer',showTime);//注冊時間事件
function?showTime(obj){?//時間處理回調函數
var?sp?=?document.getElementById("dateTime");
if(sp){
sp.innerHTML?=?obj.responseText;
}
}
function?startOrStop(obj){
var?btn?=?document.getElementById("controlBtn")
btn.value=obj.responseText;
}
Keeper.addListener('msg',showMsg,"GBK");//注冊消息事
件,最后一個參數是
//字符串編碼
function?showMsg(obj){//處理消息的回調函數
var?msg?=?document.getElementById("msg");
if(msg){
msg.value?=?obj.responseText+""n"+msg.value;
}
}
function?sendMsg()?{
var?msg?=?document.getElementById("sendMsg");
if(msg){
var?d?=?"msg="+msg.value;
sendReq('POST','./demo',d,startOrStop);
msg.value?=?"";
}
}
2.配置服務端
服務端的配置在
web.xml文件中,如下所示
keeper
keeper.servlet.Keeper
ScriptName
/keeperScript.js
1
keeper
/keeper
用在頁面包含JavaScript時,這里的src一定要和上面配
置的一至。上面的設置除了為可選的設置外,其他的都是必要的,而且不能改
變。
3.編寫事件處理代碼,消息的處理代碼如下:
protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
System.out.println("Post..");
String?msg?=?request.getParameter("msg");
Controller.action(new?SendMsg(msg),"msg");
}
class?SendMsg?implements?EventListener{
private?String?msg;
public?SendMsg(String?msg)?{
this.msg?=?msg;
}
@Override
public?void?process(HttpServletRequest?request,?HttpServletResponse?response)?{
response.setCharacterEncoding("UTF-8");
PrintWriter?out?=?null;
try?{
out?=?response.getWriter();
if(msg!=null){
out.write(msg);
}
}?catch?(IOException?e)?{
e.printStackTrace();
}
finally{
if(out?!=?null)?{
out.close();
}
}
}
}
到這時,一個基本的keeper應用就完成了。其它部分請參考附件中的例子源碼。
描述: comet的實現和應用例子
下載次數: 767
總結
以上是生活随笔為你收集整理的java comet_用java实现comet,基于 HTTP长连接的实现,用于从服务端实时发送信息到客户端...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java fork join原理_Jav
- 下一篇: java两个日期之间的日期_获取两个日期