java comet 长轮询的案例 您所在的位置:网站首页 java轮询实现 java comet 长轮询的案例

java comet 长轮询的案例

2023-08-11 10:07| 来源: 网络整理| 查看: 265

  这个案例主要是java的comet 长轮询功能的实现,看到网上的案例只是从后台推送消息到前端,而且很多都是(iframe, 流的方式), 很难找到从客户端发送消息到服务器端,服务器端接收到消息之后推送到前端,这中间涉及到Event事件处理顺序在不同的浏览器(IE,FF, Chorme)也不同。

  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(); } } }

前端页面: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

web.xml

MComet index.html           MessageServlet     MessageServlet     com.comet.servlet.MessageServlet         MessageServlet     /MessageServlet.htm   server..xml



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有