服务器servlet代码
package flowersinthesand.example; import java.io.IOException; import java.io.PrintWriter; import java.util.LinkedHashMap; import java.util.Map; import java.util.Queue; import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.LinkedBlockingQueue; import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.util.UrlEncoded; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketServlet; import com.google.gson.Gson; @WebServlet(urlPatterns = "/chat", asyncSupported = true) public class ChatServlet extends WebSocketServlet { private static final long serialVersionUID = 4805728426990609124L; private Map<String, AsyncContext> asyncContexts = new ConcurrentHashMap<String, AsyncContext>(); private Queue<ChatWebSocket> webSockets = new ConcurrentLinkedQueue<ChatWebSocket>(); private BlockingQueue<String> messages = new LinkedBlockingQueue<String>(); private Thread notifier = new Thread(new Runnable() { public void run() { while (true) { try { // Waits until a message arrives String message = messages.take(); // Sends the message to all the AsyncContext's response for (AsyncContext asyncContext : asyncContexts.values()) { try { sendMessage(asyncContext.getResponse().getWriter(), message); } catch (Exception e) { asyncContexts.values().remove(asyncContext); } } // Sends the message to all the WebSocket's connection for (ChatWebSocket webSocket : webSockets) { try { webSocket.connection.sendMessage(message); } catch (Exception e) { webSockets.remove(webSocket); } } } catch (InterruptedException e) { break; } } } }); private void sendMessage(PrintWriter writer, String message) throws IOException { // default message format is message-size ; message-data ; writer.print(message.length()); writer.print(";"); writer.print(message); writer.print(";"); writer.flush(); } @Override public void init(ServletConfig config) throws ServletException { super.init(config); notifier.start(); } // GET method is used to establish a stream connection @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Content-Type header response.setContentType("text/plain"); response.setCharacterEncoding("utf-8"); // Access-Control-Allow-Origin header response.setHeader("Access-Control-Allow-Origin", "*"); PrintWriter writer = response.getWriter(); // Id final String id = UUID.randomUUID().toString(); writer.print(id); writer.print(';'); // Padding for (int i = 0; i < 1024; i++) { writer.print(' '); } writer.print(';'); writer.flush(); final AsyncContext ac = request.startAsync(); ac.addListener(new AsyncListener() { public void onComplete(AsyncEvent event) throws IOException { asyncContexts.remove(id); } public void onTimeout(AsyncEvent event) throws IOException { asyncContexts.remove(id); } public void onError(AsyncEvent event) throws IOException { asyncContexts.remove(id); } public void onStartAsync(AsyncEvent event) throws IOException { } }); asyncContexts.put(id, ac); } // POST method is used to communicate with the server @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); AsyncContext ac = asyncContexts.get(request.getParameter("metadata.id")); if (ac == null) { return; } // close-request if ("close".equals(request.getParameter("metadata.type"))) { ac.complete(); return; } // send-request Map<String, String> data = new LinkedHashMap<String, String>(); data.put("username", request.getParameter("username")); data.put("message", request.getParameter("message")); try { messages.put(new Gson().toJson(data)); } catch (InterruptedException e) { throw new IOException(e); } } @Override public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { return new ChatWebSocket(); } class ChatWebSocket implements WebSocket.OnTextMessage { Connection connection; @Override public void onOpen(Connection connection) { this.connection = connection; webSockets.add(this); } @Override public void onClose(int closeCode, String message) { webSockets.remove(this); } @Override public void onMessage(String queryString) { // Parses query string UrlEncoded parameters = new UrlEncoded(queryString); Map<String, String> data = new LinkedHashMap<String, String>(); data.put("username", parameters.getString("username")); data.put("message", parameters.getString("message")); try { messages.put(new Gson().toJson(data)); } catch (InterruptedException e) { throw new RuntimeException(e); } } } @Override public void destroy() { messages.clear(); webSockets.clear(); asyncContexts.clear(); notifier.interrupt(); } }
html代码
<!DOCTYPE html> <html> <head> <title>Chat - Jetty 8</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="jquery-1.5.0.js"></script> <script type="text/javascript" src="jquery.stream-1.2.js"></script> <script type="text/javascript"> $.stream.setup({enableXDR: true}); var chat = { lastUsername: "Donghwan Kim", username: $.trim(window.prompt("Username?")) || "Anonymous" + $(window).width() }; $(function() { $.stream("chat", { dataType: "json", context: $("#content")[0], open: function(event, stream) { $("#editor .message").removeAttr("disabled").focus(); stream.send({username: chat.username, message: "Hello"}); }, message: function(event) { if (chat.lastUsername !== event.data.username) { $("<p />").addClass("user").text(chat.lastUsername = event.data.username).appendTo(this); } $("<p />").addClass("message").text(event.data.message).appendTo(this); this.scrollTop = this.scrollHeight; }, error: function() { $("#editor .message").attr("disabled", "disabled"); }, close: function() { $("#editor .message").attr("disabled", "disabled"); } }); $("#editor .user").text(chat.username); $("#editor .message").keyup(function(event) { if (event.which === 13 && $.trim(this.value)) { $.stream().send({username: chat.username, message: this.value}); this.value = ""; } }); $(window).resize(function() { var content = $("#content").height($(window).height() - $("#editor").outerHeight(true) - 15)[0]; content.scrollTop = content.scrollHeight; }).resize(); }); </script> <style> body {padding: 0; margin: 0; min-width: 320px; font-family: 'Trebuchet MS','Malgun Gothic',Verdana,Helvetica,Arial,sans-serif; font-size: 62.5%; color: #333333} .content {height: 100%; overflow-y: auto; padding: 14px 15px 0 25px;} .content p {margin: 0; padding: 0;} .content .user {font-size: 1.8em; color: #3e3e3e; font-weight: bold; letter-spacing: -1px; margin-top: 0.5em;} .content .message {font-size: 1.3em; color: #444444; line-height: 1.7em; word-wrap: break-word;} .editor {margin: 0 25px 15px 25px;} .editor .user {font-size: 1.5em; display: inline-block; margin: 1em;} .editor input {font-family: 'Trebuchet MS','Malgun Gothic',Verdana,Helvetica,Arial,sans-serif;} .editor .message {width: 100%; height: 28px; line-height: 28px; border: medium none; border-color: #E5E5E5 #DBDBDB #D2D2D2; border-style: solid; border-width: 1px;} </style> </head> <body> <div id="content" class="content"> <p class="user"><span>Donghwan Kim</span></p> <p class="message">Welcome to jQuery Stream!</p> </div> <div id="editor" class="editor"> <p class="user"></p> <form action="#" onsubmit="return false;"> <input class="message" type="text" disabled="disabled" /> </form> </div> </body> </html>
另需要
jquery-1.5.0.js
jquery.stream-1.2.js
参考 https://code.google.com/p/jquery-stream/
压力测试插件
相关推荐
websocket+tomcat+jetty+netty
rabbitmq+websocket(SpringBoot版)实现分布式消息推送 本来想用websocket做一个消息推送 可是分布式环境下不支持session共享因为服务器不同 所以采用 rabbitMQ+webSocket实现分布式消息推送 生产者将消息 发送给 ...
Java开发基于SpringBoot+WebSocket+Redis分布式即时通讯群聊系统。一个基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统。适用于直播间聊天、游戏内聊天、客服聊天等临时性群聊场景。 ...
websocket++库 实测可用,需要boost库
springboot+websocket+redis实现聊天室功能,可以实现私聊和群聊(并支持发送图片)
springboot+netty+websocket+redis 分布式聊天,实现简单的聊天功能
SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理系统 SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理系统 SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理...
基于Springboot websocket + js实现的即时聊天系统 基于Springboot websocket + js实现的即时聊天系统 基于Springboot websocket + js实现的即时聊天系统 基于Springboot websocket + js实现的即时聊天系统 基于...
基于ssm实现websocket长连接+redis发布/订阅消息,服务端实时推送消息至前端页面,实时通信。内含前端代码,如需sql文件请下载https://download.csdn.net/download/gmetbtgbki/10824890
websocket+Mse视频流播放器
主要介绍了SpringBoot+WebSocket+Netty实现消息推送的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
websocket +protobuf+cocos creator+客户端+服务端,已做了C++和客户端的数据相互通迅转换
1.websocket++的客户端&服务端demo 2.包含websocket++头文件 3.包含windows下使用的boost库文件及头文件
1、基于netty+websocket+springboot的实时聊天系统项目源码.zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料...
websocket+spring 前端+后端代码, 所需jar包 实测tomcat7 tomcat8都可以正常运行
SpringBoot项目整合WebSocket+netty实现前后端双向通信(同时支持前端webSocket和socket协议哦) SpringBoot项目整合WebSocket+netty实现前后端双向通信(同时支持前端webSocket和socket协议哦) SpringBoot项目整合...
phonegap+websocket+tomcat实现移动终端推送功能 ,android版
毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+...
SpringBoot整合WebSocket+nacos注册中心实现多服务通信
基于Java WebSocket 做信令服务器,使用webrtc浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。从而实现音视频通话。下载启动 输入http://localhost 就可使用