由于在网上看到有人用tomcat7+java7+extjs 实现了一个webscoket聊天室功能,我就想用tomcat8重写一遍。
于是就有了一下代码:
package com.ibcio; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import net.sf.json.JSONObject; /**接收所有来自客户端的连接请求,并定义各种事件的回调 * @author leter * @date 2016年3月8日 * @remark */ @ServerEndpoint(value = "/chat/{user}",configurator=MyConfigurator.class) public class WebSocketImpl{ //建立连接的触发的事件 @OnOpen public void start(Session session,@PathParam(value = "user") String user) { session.getUserProperties().put("user", user); // 触发连接事件,在连接池中添加连接 JSONObject result = new JSONObject(); result.element("type", "user_join"); result.element("user", user); //向所有在线用户推送当前用户上线的消息 WebSocketSessionPool.sendMessage(result.toString(),session); result = new JSONObject(); result.element("type", "get_online_user"); result.element("list", WebSocketSessionPool.getOnlineUser()); //向连接池添加当前的连接对象 WebSocketSessionPool.addMessageInbound(session,user); //向当前连接发送当前在线用户的列表 WebSocketSessionPool.sendMessageToUser(user, result.toString()); } @OnClose public void end(Session session) { // 触发关闭事件,在连接池中移除连接 String user = session.getUserProperties().get("user").toString(); WebSocketSessionPool.removeMessageInbound(user); JSONObject result = new JSONObject(); result.element("type", "user_leave"); result.element("user", user); //向在线用户发送当前用户退出的消息 WebSocketSessionPool.sendMessage(result.toString(),session); } //客户端发送消息到服务器时触发事件 @OnMessage public void prcess(String message, Session session){ //向所有在线用户发送消息 WebSocketSessionPool.sendMessage(message.toString(),session); } }
package com.ibcio; import javax.websocket.server.ServerEndpointConfig.Configurator; /**因为每次来一个链接都会生成一个新的WebSocketImpl,这样比较耗费资源。 * 统一配置只使用一个WebSocketImpl * @author leter * @date 2016年3月8日 * @remark */ public class MyConfigurator extends Configurator { private WebSocketImpl webSocket = new WebSocketImpl(); @Override public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException { return (T) webSocket; } }
package com.ibcio; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.websocket.Session; /**存储所有在线用户的信息,执行上线下线发送消息时需要执行的方法。 * @author leter * @date 2016年3月8日 * @remark */ public class WebSocketSessionPool { // 保存连接的MAP容器 private static final Map<String, Session> connections = Collections.synchronizedMap(new HashMap<String, Session>()); // 向连接池中添加连接 public static void addMessageInbound(Session session, String user) { // 添加连接 System.out.println("user : " + user + " join.."); connections.put(user, session); } // 获取所有的在线用户 public static Set<String> getOnlineUser() { return connections.keySet(); } public static void removeMessageInbound(String user) { // 移除连接 System.out.println("user : " + user + " exit.."); connections.remove(user); } public static void sendMessageToUser(String user, String message) { try { // 向特定的用户发送数据 System.out.println("send message to user : " + user+ " ,message content : " + message); Session session = connections.get(user); if (session != null) { session.getBasicRemote().sendText(message); } } catch (IOException e) { e.printStackTrace(); } } // 向所有的用户发送消息 public static void sendMessage(String message, Session session) { try { for (String key : connections.keySet()) { connections.get(key).getBasicRemote().sendText(message); } } catch (IOException e) { e.printStackTrace(); } } }
前台index.jsp代码
<%@ page language="java" pageEncoding="UTF-8" import="java.util.UUID"%> <% String user = "user"+UUID.randomUUID(); pageContext.setAttribute("user", user); %> <html> <head> <title>WebSocket 聊天室</title> <!-- 引入CSS文件 --> <link rel="stylesheet" type="text/css" href="ext4/resources/css/ext-all.css"> <link rel="stylesheet" type="text/css" href="ext4/shared/example.css" /> <link rel="stylesheet" type="text/css" href="css/websocket.css" /> <!-- 映入Ext的JS开发包,及自己实现的webscoket. --> <script type="text/javascript" src="ext4/ext-all-debug.js"></script> <script type="text/javascript" src="websocket.js"></script> <script type="text/javascript"> var user = "${user}"; </script> </head> <body> <h1>WebSocket聊天室</h1> <p>通过HTML5标准提供的API与Ext富客户端框架相结合起来,实现聊天室,有以下特点:</p> <ul class="feature-list" style="padding-left: 10px;"> <li>实时获取数据,由服务器推送,实现即时通讯</li> <li>利用WebSocket完成数据通讯,区别于轮询,长连接等技术,节省服务器资源</li> <li>结合Ext进行页面展示</li> <li>用户上线下线通知</li> </ul> <div id="websocket_button"></div> </body> </html>
websokect.js
//用于展示用户的聊天信息 Ext.define('MessageContainer', { extend : 'Ext.view.View', trackOver : true, multiSelect : false, itemCls : 'l-im-message', itemSelector : 'div.l-im-message', overItemCls : 'l-im-message-over', selectedItemCls : 'l-im-message-selected', style : { overflow : 'auto', backgroundColor : '#fff' }, tpl : [ '<div class="l-im-message-warn">交谈中请勿轻信汇款、中奖信息、陌生电话。 请遵守相关法律法规。</div>', '<tpl for=".">', '<div class="l-im-message">', '<div class="l-im-message-header l-im-message-header-{source}">{from} {timestamp}</div>', '<div class="l-im-message-body">{content}</div>', '</div>', '</tpl>'], messages : [], initComponent : function() { var me = this; me.messageModel = Ext.define('Leetop.im.MessageModel', { extend : 'Ext.data.Model', fields : ['from', 'timestamp', 'content', 'source'] }); me.store = Ext.create('Ext.data.Store', { model : 'Leetop.im.MessageModel', data : me.messages }); me.callParent(); }, //将服务器推送的信息展示到页面中 receive : function(message) { var me = this; message['timestamp'] = Ext.Date.format(new Date(message['timestamp']), 'H:i:s'); if(message.from == user){ message.source = 'self'; }else{ message.source = 'remote'; } me.store.add(message); if (me.el.dom) { me.el.dom.scrollTop = me.el.dom.scrollHeight; } } }); Ext.onReady(function() { //创建用户输入框 var input = Ext.create('Ext.form.field.HtmlEditor', { region : 'south', height : 120, enableFont : false, enableSourceEdit : false, enableAlignments : false, listeners : { initialize : function() { Ext.EventManager.on(me.input.getDoc(), { keyup : function(e) { if (e.ctrlKey === true && e.keyCode == 13) { e.preventDefault(); e.stopPropagation(); send(); } } }); } } }); //创建消息展示容器 var output = Ext.create('MessageContainer', { region : 'center' }); var dialog = Ext.create('Ext.panel.Panel', { region : 'center', layout : 'border', items : [input, output], buttons : [{ text : '发送', handler : send }] }); var websocket; //初始话WebSocket function initWebSocket() { if (window.WebSocket) { websocket = new WebSocket(encodeURI('ws://localhost/webscoket/chat/'+user)); websocket.onopen = function() { //连接成功 win.setTitle(title + ' (已连接)'); } websocket.onerror = function() { //连接失败 win.setTitle(title + ' (连接发生错误)'); } websocket.onclose = function() { //连接断开 win.setTitle(title + ' (已经断开连接)'); } //消息接收 websocket.onmessage = function(message) { var message = JSON.parse(message.data); //接收用户发送的消息 if (message.type == 'message') { output.receive(message); } else if (message.type == 'get_online_user') { //获取在线用户列表 var root = onlineUser.getRootNode(); Ext.each(message.list,function(user){ var node = root.createNode({ id : user, text : user, iconCls : 'user', leaf : true }); root.appendChild(node); }); } else if (message.type == 'user_join') { //用户上线 var root = onlineUser.getRootNode(); var user = message.user; var node = root.createNode({ id : user, text : user, iconCls : 'user', leaf : true }); root.appendChild(node); } else if (message.type == 'user_leave') { //用户下线 var root = onlineUser.getRootNode(); var user = message.user; var node = root.findChild('id',user); root.removeChild(node); } } } }; //在线用户树 var onlineUser = Ext.create('Ext.tree.Panel', { title : '在线用户', rootVisible : false, region : 'east', width : 150, lines : false, useArrows : true, autoScroll : true, split : true, iconCls : 'user-online', store : Ext.create('Ext.data.TreeStore', { root : { text : '在线用户', expanded : true, children : [] } }) }); var title = '欢迎您:' + user; //展示窗口 var win = Ext.create('Ext.window.Window', { title : title + ' (未连接)', layout : 'border', iconCls : 'user-win', minWidth : 650, minHeight : 460, width : 650, animateTarget : 'websocket_button', height : 460, items : [dialog,onlineUser], border : false, listeners : { render : function() { initWebSocket(); } } }); win.show(); //发送消息 function send() { var message = {}; if (websocket != null) { if (input.getValue()) { Ext.apply(message, { from : user, content : input.getValue(), timestamp : new Date().getTime(), type : 'message' }); websocket.send(JSON.stringify(message)); //output.receive(message); input.setValue(''); } } else { Ext.Msg.alert('提示', '您已经掉线,无法发送消息!'); } } });
我使用的开发环境是eclipse kepler + tomcat8.0.32+jdk7.x
以下是tomat7实现和tomcat8实现的源码。
相关推荐
基于SpringBoot+FreeMarker+MyBatis+ExtJs实现的一个通用后台管理系统,界面美观,适合快速迭代开发 项目说明 技术栈: SpringBoot MyBatis Redis MySQL FreeMarker ExtJs 基于SpringBoot+FreeMarker+MyBatis+...
1、基于SpringBoot+FreeMarker+MyBatis+ExtJs实现的一个通用后台管理系统源码(适合快速迭代开发).zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计...
1. **WebSocket协议**:WebSocket基于TCP,通过HTTP/1.1的Upgrade头字段进行初始化,之后建立一个长期存在的连接,允许双向数据流。 2. **Tomcat的WebSocket支持**:Tomcat从7.0版本开始内置了对WebSocket的支持,...
在本项目中,“Extjs实现的聊天室”利用了ExtJS的组件化特性和WebSocket技术,构建了一个实时的在线聊天平台。 WebSocket是一种在客户端和服务器之间建立长连接的协议,允许双方进行全双工通信,即数据可以在任意...
《基于SpringBoot+FreeMarker+MyBatis+ExtJs实现的通用后台管理系统详解》 在当前的IT领域,SpringBoot框架已经成为开发企业级应用的首选工具,尤其在构建后台管理系统时,其便捷性和高效性尤为突出。本项目“基于...
本资源中的源码都是经过本地编译过可运行的,下载后按照文档配置好环境就可以运行。资源项目的难度比较适中,内容都是经过助教老师审定过的,应该能够满足学习、使用需求,如果有需要的话可以放心下载使用。...
【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。...基于SpringBoot+FreeMarker+MyBatis+ExtJs实现的一个通用后台管理系统源码(适合快速迭代开发).zip
【标题】"spring+mvc+mybatis+extjs整合"是一个经典的Java Web开发框架组合,广泛应用于企业级应用。这个项目结合了Spring MVC作为控制层,MyBatis作为数据访问层,以及ExtJS作为前端展示层,构建了一个完整的三层...
该项目是一个实时聊天应用程序,利用了Java技术栈与现代Web通信技术WebSocket,构建在Tomcat7服务器上,并且前端界面采用了ExtJS框架。以下是对这些关键知识点的详细解释: 1. **WebSocket**: WebSocket是一种在...
easyjweb+jpa+spring+extjs续:实现了综合配货系统后台管理,由于时间关系,有些细节没有考虑到,但是框架打气来,没有什么大问题,由于时间关系现在就更新到这,需要的请下载,认真学完现在更新的和以后更新的,项目...
本话题主要关注如何使用Java后端和ExtJS前端框架来实现单文件上传的流程。下面将详细讲解这个过程涉及的关键知识点。 首先,我们来看Java文件上传。在Java中,处理文件上传主要依赖于Servlet API中的`Part`接口,这...
标题中的“Extjs+java+swf多文件上传进度条显示项目”是一个综合性的Web开发实践,涉及到前端的用户界面、后端的数据处理以及文件上传过程中进度反馈的实现。这个项目利用了Extjs库来构建用户界面,Java作为服务器端...
用Java写的项目,项目真实可靠,可用作本科毕业设计,欢迎大家下载学习。用Java写的项目,项目真实可靠,可用作本科毕业设计,欢迎大家下载学习。用Java写的项目,项目真实可靠,可用作本科毕业设计,欢迎大家下载...
8. **异常处理**:Java后端需要良好的异常处理机制,确保错误能够被妥善处理,并向ExtJS前端发送有意义的错误信息。 在实际项目中,开发者需要熟练掌握Java和ExtJS的API,理解它们的交互方式,以便创建出高效且用户...
(基于JSP的完整java毕业设计)ExtJS 2.2 图书管理系统(基于JSP的完整java毕业设计)ExtJS 2.2 图书管理系统(基于JSP的完整java毕业设计)ExtJS 2.2 图书管理系统(基于JSP的完整java毕业设计)ExtJS 2.2 图书管理...
它可以基于诸如Node.js的Socket.IO库或者Java的Jetty等WebSocket实现。 2. **EXTJS前端**:通过EXTJS的组件库,构建用户界面,如聊天窗口、好友列表、消息输入框等,并通过WebSocket API与服务器保持实时通信。 3....
基于HTML5,extjs、webSocket的聊天室源代码