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>
然后就可以打开多个浏览器测试了。。。