`

基于tomcat8+java7+extjs 的webscoket 聊天室实现

 
阅读更多

    由于在网上看到有人用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 + '&nbsp;&nbsp;(已连接)');
					}
					websocket.onerror = function() {
						//连接失败
						win.setTitle(title + '&nbsp;&nbsp;(连接发生错误)');
					}
					websocket.onclose = function() {
						//连接断开
						win.setTitle(title + '&nbsp;&nbsp;(已经断开连接)');
					}
					//消息接收
					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 + '&nbsp;&nbsp;(未连接)',
						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实现的源码。

    

分享到:
评论

相关推荐

    SNS单模无芯光纤仿真与传感器结构特性分析——基于Rsoft beamprop模块

    内容概要:本文主要探讨了SNS单模无芯光纤的仿真分析及其在通信和传感领域的应用潜力。首先介绍了模间干涉仿真的重要性,利用Rsoft beamprop模块模拟不同模式光在光纤中的传播情况,进而分析光纤的传输性能和模式特性。接着讨论了光纤传输特性的仿真,包括损耗、色散和模式耦合等参数的评估。随后,文章分析了光纤的结构特性,如折射率分布、包层和纤芯直径对性能的影响,并探讨了镀膜技术对光纤性能的提升作用。最后,进行了变形仿真分析,研究外部因素导致的光纤变形对其性能的影响。通过这些分析,为优化光纤设计提供了理论依据。 适合人群:从事光纤通信、光学工程及相关领域的研究人员和技术人员。 使用场景及目标:适用于需要深入了解SNS单模无芯光纤特性和优化设计的研究项目,旨在提高光纤性能并拓展其应用场景。 其他说明:本文不仅提供了详细的仿真方法和技术细节,还对未来的发展方向进行了展望,强调了SNS单模无芯光纤在未来通信和传感领域的重要地位。

    发那科USM通讯程序socket-rece

    发那科USM通讯程序socket-set

    嵌入式八股文面试题库资料知识宝典-WIFI.zip

    嵌入式八股文面试题库资料知识宝典-WIFI.zip

    JS+HTML源码与image

    源码与image

    物流行业车辆路径优化:基于遗传算法和其他优化算法的MATLAB实现及应用

    内容概要:本文详细探讨了物流行业中路径规划与车辆路径优化(VRP)的问题,特别是针对冷链物流、带时间窗的车辆路径优化(VRPTW)、考虑充电桩的车辆路径优化(EVRP)以及多配送中心情况下的路径优化。文中不仅介绍了遗传算法、蚁群算法、粒子群算法等多种优化算法的理论背景,还提供了完整的MATLAB代码及注释,帮助读者理解这些算法的具体实现。此外,文章还讨论了如何通过MATLAB处理大量数据和复杂计算,以得出最优的路径方案。 适合人群:从事物流行业的研究人员和技术人员,尤其是对路径优化感兴趣的开发者和工程师。 使用场景及目标:适用于需要优化车辆路径的企业和个人,旨在提高配送效率、降低成本、确保按时交付货物。通过学习本文提供的算法和代码,读者可以在实际工作中应用这些优化方法,提升物流系统的性能。 其他说明:为了更好地理解和应用这些算法,建议读者参考相关文献和教程进行深入学习。同时,实际应用中还需根据具体情况进行参数调整和优化。

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_8.doc.zip

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_8.doc.zip

    基于灰狼优化算法的城市路径规划Matlab实现——解决TSP问题

    内容概要:本文介绍了基于灰狼优化算法(GWO)的城市路径规划优化问题(TSP),并通过Matlab实现了该算法。文章详细解释了GWO算法的工作原理,包括寻找猎物、围捕猎物和攻击猎物三个阶段,并提供了具体的代码示例。通过不断迭代优化路径,最终得到最优的城市路径规划方案。与传统TSP求解方法相比,GWO算法具有更好的全局搜索能力和较快的收敛速度,适用于复杂的城市环境。尽管如此,算法在面对大量城市节点时仍面临运算时间和参数设置的挑战。 适合人群:对路径规划、优化算法感兴趣的科研人员、学生以及从事交通规划的专业人士。 使用场景及目标:①研究和开发高效的路径规划算法;②优化城市交通系统,提升出行效率;③探索人工智能在交通领域的应用。 其他说明:文中提到的代码可以作为学习和研究的基础,但实际应用中需要根据具体情况调整算法参数和优化策略。

    嵌入式八股文面试题库资料知识宝典-Intel3.zip

    嵌入式八股文面试题库资料知识宝典-Intel3.zip

    嵌入式八股文面试题库资料知识宝典-2019京东C++.zip

    嵌入式八股文面试题库资料知识宝典-2019京东C++.zip

    嵌入式八股文面试题库资料知识宝典-北京光桥科技有限公司面试题.zip

    嵌入式八股文面试题库资料知识宝典-北京光桥科技有限公司面试题.zip

    物理学领域十字形声子晶体的能带与传输特性研究及应用

    内容概要:本文详细探讨了十字形声子晶体的能带结构和传输特性。首先介绍了声子晶体作为新型周期性结构在物理学和工程学中的重要地位,特别是十字形声子晶体的独特结构特点。接着从散射体的形状、大小、排列周期等方面分析了其对能带结构的影响,并通过理论计算和仿真获得了能带图。随后讨论了十字形声子晶体的传输特性,即它对声波的调控能力,包括传播速度、模式和能量分布的变化。最后通过大量实验和仿真验证了理论分析的正确性,并得出结论指出散射体的材料、形状和排列方式对其性能有重大影响。 适合人群:从事物理学、材料科学、声学等相关领域的研究人员和技术人员。 使用场景及目标:适用于希望深入了解声子晶体尤其是十字形声子晶体能带与传输特性的科研工作者,旨在为相关领域的创新和发展提供理论支持和技术指导。 其他说明:文中还对未来的研究方向进行了展望,强调了声子晶体在未来多个领域的潜在应用价值。

    嵌入式系统开发_USB主机控制器_Arduino兼容开源硬件_基于Mega32U4和MAX3421E芯片的USB设备扩展开发板_支持多种USB外设接入与控制的通用型嵌入式开发平台_.zip

    嵌入式系统开发_USB主机控制器_Arduino兼容开源硬件_基于Mega32U4和MAX3421E芯片的USB设备扩展开发板_支持多种USB外设接入与控制的通用型嵌入式开发平台_

    e2b8a-main.zip

    e2b8a-main.zip

    少儿编程scratch项目源代码文件案例素材-火柴人跑酷(2).zip

    少儿编程scratch项目源代码文件案例素材-火柴人跑酷(2).zip

    【HarmonyOS分布式技术】远程启动子系统详解:跨设备无缝启动与智能协同的应用场景及未来展望

    内容概要:本文详细介绍了HarmonyOS分布式远程启动子系统,该系统作为HarmonyOS的重要组成部分,旨在打破设备间的界限,实现跨设备无缝启动、智能设备选择和数据同步与连续性等功能。通过分布式软总线和分布式数据管理技术,它能够快速、稳定地实现设备间的通信和数据同步,为用户提供便捷的操作体验。文章还探讨了该系统在智能家居、智能办公和教育等领域的应用场景,展示了其在提升效率和用户体验方面的巨大潜力。最后,文章展望了该系统的未来发展,强调其在技术优化和应用场景拓展上的无限可能性。 适合人群:对HarmonyOS及其分布式技术感兴趣的用户、开发者和行业从业者。 使用场景及目标:①理解HarmonyOS分布式远程启动子系统的工作原理和技术细节;②探索该系统在智能家居、智能办公和教育等领域的具体应用场景;③了解该系统为开发者提供的开发优势和实践要点。 其他说明:本文不仅介绍了HarmonyOS分布式远程启动子系统的核心技术和应用场景,还展望了其未来的发展方向。通过阅读本文,用户可以全面了解该系统如何通过技术创新提升设备间的协同能力和用户体验,为智能生活带来新的变革。

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_1.zip

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_1.zip

    少儿编程scratch项目源代码文件案例素材-激光反弹.zip

    少儿编程scratch项目源代码文件案例素材-激光反弹.zip

    COMSOL相控阵检测技术在有机玻璃斜楔中检测工件内部缺陷的应用研究

    内容概要:本文详细介绍了COMSOL相控阵检测技术在有机玻璃斜楔上放置16阵元进行工件内部缺陷检测的方法。首先阐述了相控阵检测技术的基本原理,特别是通过控制各阵元的激发时间和相位来实现声波的聚焦和扫描。接着,重点解析了横孔缺陷的反射接收波,解释了波的折射现象及其背后的物理原因。最后,通过实例展示了COMSOL模拟声波传播过程的成功应用,验证了该技术的有效性和准确性。 适合人群:从事固体力学、无损检测领域的研究人员和技术人员,尤其是对相控阵检测技术和COMSOL仿真感兴趣的读者。 使用场景及目标:适用于需要精确检测工件内部缺陷的研究和工业应用场景,旨在提高检测精度和效率,确保产品质量和安全。 其他说明:文中提到的声速匹配现象有助于理解波在不同介质间的传播特性,这对优化检测参数设置有重要意义。

    少儿编程scratch项目源代码文件案例素材-极速奔跑者.zip

    少儿编程scratch项目源代码文件案例素材-极速奔跑者.zip

    嵌入式八股文面试题库资料知识宝典-微软_interview.zip

    嵌入式八股文面试题库资料知识宝典-微软_interview.zip

Global site tag (gtag.js) - Google Analytics