java comet例子_java comet 长轮询的案例

这个案例主要是java的comet 长轮询功能的实现,看到网上的案例只是从后台推送消息到前端,而且很多都是(iframe, 流的方式),

很难找到从客户端发送消息到服务器端,服务器端接收到消息之后推送到前端,这中间涉及到Event事件处理顺序在不同的浏览器(IE,FF, Chorme)也不同。

PS:主要说的就是是IE。以下内容是经过我测试发现的,如果有说的不对的,可以提出交流。

* 对于http://bbs..net/topics/391951969的问题,是由于tomcat6.x在解析post请求参数的时候出现了异常(算是bug),换成7.x就可以了。

public void event(CometEvent evt) {

try {

//对于event而言,会存在多个状态,

if(evt.getEventType() == CometEvent.EventType.BEGIN) {

//请求开始触发(所有浏览器一致)

} else if(evt.getEventType() == CometEvent.EventType.END) {

//请求完成后触发(IE:是在下个请求开始前触发,Chrome是在请求之后触发,FF应该和Chrome是一致的)

/****这是最大的区别,这个花费了我好长时间测试,本来想在CSND上求救(http://bbs..net/topics/391951969),居然两天每人回,调试了老半天,问题终于被我发现了。唉不容易啊。****/

} else if(evt.getEventType() == CometEvent.EventType.ERROR) {

//请求出现错误触发

} else if(evt.getEventType() == CometEvent.EventType.READ) {

//请求读的时候触发

}

} catch(IOException e) {

e.printStackTrace();

}

说了那么多贴上源码:

类:MessageServlet 建立长连接

内部类 : RandomThread 产生消息

package com.comet.servlet;

import java.io.IOException;

import java.util.Random;

import javax.servlet.Servlet;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;

import org.apache.catalina.CometProcessor;

/**

* Servlet implementation class SecondServlet

*/

public class MessageServlet extends HttpServlet implements CometProcessor {

private static final long serialVersionUID = 1L;

private MessageSender msgSender = MessageSender.getInstance();

/**

* @see CometProcessor#event(CometEvent)

*/

public void event(CometEvent evt) {

/**

* evt 方法用来处理各种请求,可以根据状态的不同得到各种响应

* 同时可以不断根据自己的需求向客户端发送信息

*/

HttpServletResponse response = evt.getHttpServletResponse();

HttpServletRequest request = evt.getHttpServletRequest();

try {

String sessionId = request.getSession().getId();

//对于event而言,会存在多个状态,

if(evt.getEventType() == CometEvent.EventType.BEGIN) {

//在begin的时候操作

System.out.println(response + "正在建立连接.");

msgSender.setConn(sessionId, response);

} else if(evt.getEventType() == CometEvent.EventType.END) {

//在结束的时候

System.out.println(response + "已经结束.");

msgSender.remove(sessionId, response);

evt.close();

} else if(evt.getEventType() == CometEvent.EventType.ERROR) {

//在发送错误的时候

System.out.println(response + "发生错误.");

msgSender.remove(sessionId, response);

evt.close();

} else if(evt.getEventType() == CometEvent.EventType.READ) {

//还在读取数据的状态

throw new RuntimeException("该状态无法操作");

}

} catch(IOException e) {

e.printStackTrace();

}

}

/**

* @see Servlet#init(ServletConfig)

*/

public void init(ServletConfig config) throws ServletException {

Thread msgThread = new Thread(msgSender);

msgThread.setDaemon(true);//后台进程

msgThread.start();

RandomThread rr = new RandomThread();

Thread rt = new Thread(rr);

rt.start();

super.init();

}

@Override

public void destroy() {

msgSender.close();

super.destroy();

}

}

class RandomThread implements Runnable {

private final static Random ran = new Random(10);

private boolean running = true;

private MessageSender msgSender = MessageSender.getInstance();

@Override

public void run() {

try {

while(running) {

Thread.sleep(4000);

int num = ran.nextInt(10);

System.out.println("产生消息:"+num);

msgSender.sendMsg(num + "");

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

类:MessageSender 发送消息

package com.comet.servlet;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Set;

import javax.servlet.http.HttpServletResponse;

/**

* 消息发送类

* @author xingyakai

*

*/

public class MessageSender implements Runnable {

private String msg = new String();

Map> conns = new HashMap>();

public boolean running = true;

private static MessageSender messageSender = new MessageSender();

private MessageSender() {}

public static MessageSender getInstance() {

return messageSender;

}

public void close() {

running = false;

}

public synchronized void sendMsg(String msg) {

this.msg = msg;

this.notify();

}

public void remove(String sessionId, HttpServletResponse response) {

synchronized (this.conns) {

conns.get(sessionId).remove(response);

}

}

public void setConn(String sessionId, HttpServletResponse conn) {

synchronized (this.conns) {

List _responses = this.conns.get(sessionId);

if(_responses == null) {

_responses = new ArrayList();

}

_responses.add(conn);

conns.put(sessionId, _responses);

}

}

public List getAllResponse() {

List _allResponses = new ArrayList();

Set _sessionIds = conns.keySet();

for(String sessionId : _sessionIds) {

_allResponses.addAll(conns.get(sessionId));

}

return _allResponses;

}

@Override

public void run() {

try {

while(running) {

String msg = "";

if(this.msg == null || this.msg == "") {

synchronized (this) {

this.wait();

}

}

msg = this.msg;

this.msg = null;

synchronized (this.conns) {

List responses = this.getAllResponse();

for(HttpServletResponse response : responses) {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

System.out.println("发送消息:" + msg);

out.print(msg);

out.flush();

out.close();

out = null;

}

}

}

} catch (InterruptedException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

前端页面:index.html

$(function() {

function poll() {

$.ajax({

url:'http://localhost:8080/MComet/MessageServlet.htm?time='+(new Date()).getTime(),

type: 'POST',

dataType: 'text',

success: function(data) {

$('#ctn').append(data + '');

poll();

},

error: function() {

$('#ctn').append('error');

}

});

}

poll();

});

function sendMsg() {

$.post('sendMsg.jsp', function(data) {});

}

Comet

发送

前端页面:sendMsg.jsp

MessageSender sender = MessageSender.getInstance();

sender.sendMsg("Test");

%>

web.xml

MComet

index.html

MessageServlet

MessageServlet

com.comet.servlet.MessageServlet

MessageServlet

/MessageServlet.htm

server..xml

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值