欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

comet 推送 消息 聊天

程序员文章站 2022-05-06 15:10:36
...

 

需要的jar包以及基础的配置参考:

tomcat comet 推送 技术 入门 

直接切入正题:

 

首先引入tomcat的lib目录下的jar包:

 

catalina.jar,servlet-api.jar

 

另外要修改tomcat的server.xml,将protocal="http/1.1"什么的修改为:

 

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" 
               connectionTimeout="20000" 
               redirectPort="8443" />

 

 

这样就让tomcat支持推送功能了

 

首先是servlet(带有注释):

 

package nio.comet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

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;

public class ChatCometServlet extends HttpServlet implements CometProcessor{
	private static final long serialVersionUID = 1L;
	private List<CometEvent> events = new ArrayList<CometEvent>();

	@Override
	public void event(CometEvent event) throws IOException, ServletException {
		HttpServletRequest request = event.getHttpServletRequest();
		String path = request.getRequestURI();
		if(path.indexOf("setComet") != -1){
			//发送消息的请求
			String message = request.getParameter("message");
			//遍历所有的CometEvent,将消息发送出去
			synchronized(events){
				//使用list的遍历器
				Iterator<CometEvent> iterator = events.iterator(); 
				CometEvent e = null;
				while(iterator.hasNext()){
					e = iterator.next();
					HttpServletResponse res = e.getHttpServletResponse();
					//设置响应的编码和类型
					res.setCharacterEncoding("utf-8");
					res.setContentType("text/plain");
					PrintWriter writer = res.getWriter();
					writer.write(message);
					writer.flush();
					//一定要调用list保存的CometEvent对象的close方法关闭,这样才可以及时将消息推送出去
					e.close();
					//删除的时候要使用iterator的删除方法,否则可能会引发cuncurrentModifyException
					iterator.remove();
				}
			}
			//最后关闭当前请求的CometEvent
			event.close();
			return;
		}else if(path.indexOf("getComet") != -1){
			//获取消息的请求
			if(event.getEventType() == CometEvent.EventType.BEGIN){
				//begin阶段,设置超时时间,并将CometEvent对于保存到list中,其他阶段均返回ERROR(简单处理)
				event.setTimeout(20000);
				synchronized(events){
					events.add(event);
				}
				return;
			}else if(event.getEventType() == CometEvent.EventType.END){
				synchronized(events){
					HttpServletResponse res = event.getHttpServletResponse();
					res.setCharacterEncoding("utf-8");
					res.setContentType("text/plain");
					PrintWriter writer = res.getWriter();
					writer.write("ERROR");
					writer.flush();
					event.close();
					events.remove(event);
				}
				return;
			}else if(event.getEventType() == CometEvent.EventType.ERROR){
				synchronized(events){
					HttpServletResponse res = event.getHttpServletResponse();
					res.setCharacterEncoding("utf-8");
					res.setContentType("text/plain");
					PrintWriter writer = res.getWriter();
					writer.write("ERROR");
					writer.flush();
					event.close();
					events.remove(event);
				}
				return;
			}else if(event.getEventType() == CometEvent.EventType.READ){
				synchronized(events){
					HttpServletResponse res = event.getHttpServletResponse();
					res.setCharacterEncoding("utf-8");
					res.setContentType("text/plain");
					PrintWriter writer = res.getWriter();
					writer.write("ERROR");
					writer.flush();
					event.close();
					events.remove(event);
				}
				return;
			}
		}
	}
}

 

 

然后再web.xml中配置servlet:

 

	<servlet>
		<servlet-name>mycomet</servlet-name>
		<servlet-class>nio.comet.ChatCometServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>mycomet</servlet-name>
		<url-pattern>/comet/*</url-pattern>
	</servlet-mapping>

 

然后就是页面了(里面需要引入jquery):

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'chat.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<script type="text/javascript" src="upload/js/jquery.min.js"></script>
	<script type="text/javascript">
		$(function(){
			//页面加载完之后就发起读取消息的长连接
			read();
		});
		//发送消息
		function send(){
			var f = document.forms['cometForm'];
			$.post("comet/setComet",$(f).serialize());
		}
		//读取消息
		function read(){
			$.ajax({
			   type: "POST",
			   url: "comet/getComet",
			   success: function(data){
			     if("ERROR" != data){
			    	 $("#show").html($("#show").html()+'<br/>'+data);
			     }
				 read();
			   }
			});
		}
	</script>
  </head>
  <body>
    <form name="cometForm">
	     <input type="text" name="message"/>
	     <input type="button" value="send" onclick="send();"/>
    </form>
      消息:
    <div id="show"></div>
  </body>
</html>

 

然后就可以打开多个浏览器测试了。。。