PS:主要说的就是是IE。以下内容是经过我测试发现的,如果有说的不对的,可以提出交流。
* 对于http://bbs.csdn.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.csdn.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();
}
}
}
Comet
前端页面:sendMsg.jsp
<%@page import="com.comet.servlet.MessageSender"%>
<%
MessageSender sender = MessageSender.getInstance();
sender.sendMsg("Test");
%>
web.xml
MComet
index.html
MessageServlet
MessageServlet
com.comet.servlet.MessageServlet
MessageServlet
/MessageServlet.htm
server..xml