HTML5 WebSocket+Tomcat实现真●Web版即时聊天室(单人+多人)

先进入login.jsp页面,填写你的昵称,登录进入chat.jsp页面,我打开了四个页面模拟四个用户,用户姓名放在session里,方便后台的操作,当然了根据系统需要你可以放用户ID

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><style>body {padding: 20px;}#message {height: 300px;border:1px solid;overflow: auto;}</style><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>WebIM</title><script type="text/javascript" src="js/jquery-1.7.2.min.js"></script><%String name = request.getParameter("username");session.setAttribute("user", name);%><script type="text/javascript">var self = "<%=name%>";var ws = null;function startWebSocket() {if ('WebSocket' in window)ws = new WebSocket("ws://localhost:8080/WebSocketUser/websocket.do");else if ('MozWebSocket' in window)ws = new MozWebSocket("ws://localhost:8080/WebSocketUser/websocket.do");elsealert("not support");ws.onmessage = function(evt){var data = evt.data;var obj = eval ('(' + data + ')');//将字符串转换成JSONif(obj.type == 'message'){setMessageInnerHTML(obj.data);}else if(obj.type == 'user'){var userArry = obj.data.split(',');$("#userlist").empty();$("#userlist").append("<option value ='all'>所有人</option>");$.each(userArry,function(n,value){if(value != self && value != 'admin'){$("#userlist").append('<option value = '+value+'>'+value+'</option>');}});}};ws.onclose = function(evt) {$('#denglu').html("离线");};ws.onopen = function(evt) {$('#denglu').html("在线");$('#userName').html(self);};}function setMessageInnerHTML(innerHTML){var temp = $('#message').html();temp += innerHTML + '<br/>';$('#message').html(temp);}function sendMsg() {var fromName = self;var toName = $("#userlist").val(); //发给谁var content = $("#writeMsg").val(); //发送内容ws.send(fromName + "," + toName + "," + content);}</script></head><body onload="startWebSocket();"><h1>WebIM</h1>登录状态:<span id="denglu" style="color: red;">正在登录</span><br> 昵称:<span id="userName"></span><br><br> To:<select id='userlist'></select><span style="color: red;">*</span>请选择聊天对象<br> 发送内容:<input type="text" id="writeMsg" value="嗨~"/><br> 聊天框:<div id="message"></div><br><input type="button" value="send" onclick="sendMsg()"/></body></html>

样式比较粗糙,没有在界面上花时间,和之前的点对点通信并没有多大的区别,主要就是onMessage那里,根据后台推送的消息,判断消息类型,如果为‘user’,意思是有新用户登录,这个时候要将select里的option更新,效果就是,当前有多少人在线,就有多少个用户选项,当然了不包括自己!如果类型为’message’,就是普通的消息类型了。

后台的代码主要改动的是MyMessageInbound文件,代码如下

package socket;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import org.apache.catalina.websocket.MessageInbound;import org.apache.catalina.websocket.WsOutbound;import util.MessageUtil;public class MyMessageInbound extends MessageInbound {private String name;public MyMessageInbound() {super();}public MyMessageInbound(String name) {super();this.name = name;}@Override protected void onBinaryMessage(ByteBuffer arg0) throws IOException {}@Override protected void onTextMessage(CharBuffer msg) {HashMap<String,String> messageMap = MessageUtil.getMessage(msg); //处理消息类String fromName = messageMap.get("fromName"); //消息来自人 的userIdString toName = messageMap.get("toName");//消息发往人的 userIdString mapContent = messageMap.get("content");if("all".equals(toName)){String msgContentString = fromName + "对所有人说: " + mapContent; //构造发送的消息String content = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString);broadcastAll(content);}else{try {singleChat(fromName,toName,mapContent);} catch (IOException e) {e.printStackTrace();}}}private void singleChat(String fromName, String toName, String mapContent) throws IOException {HashMap<String, MessageInbound> userMsgMap = InitServlet.getSocketList();MessageInbound messageInbound = userMsgMap.get(toName); //在仓库中取出发往人的MessageInboundMessageInbound messageFromInbound = userMsgMap.get(fromName);if(messageInbound!=null && messageFromInbound!=null){//如果发往人 存在进行操作WsOutbound outbound = messageInbound.getWsOutbound();WsOutbound outFromBound = messageFromInbound.getWsOutbound();String msgContentString = fromName + "对" + toName + "说: " + mapContent; //构造发送的消息String contentTemp = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString);outFromBound.writeTextMessage(CharBuffer.wrap(contentTemp.toCharArray()));outbound.writeTextMessage(CharBuffer.wrap(contentTemp.toCharArray())); //outFromBound.flush();outbound.flush();}else{String content = MessageUtil.sendContent(MessageUtil.MESSAGE,"客服不在线请留言…");broadcastAll(content);}}@Override protected void onClose(int status) { if(name!=null){InitServlet.getSocketList().remove(name);//删除客服ID与用户System.out.println("用户" + name + "退出");}String names = getNames();String content = MessageUtil.sendContent(MessageUtil.USER,names);broadcastAll(content);super.onClose(status);}@Overrideprotected void onOpen(WsOutbound outbound) { super.onOpen(outbound);if(name!=null){InitServlet.getSocketList().put(name, this);//存放客服ID与用户}String names = getNames();String content = MessageUtil.sendContent(MessageUtil.USER,names);broadcastAll(content);}private String getNames() {Map<String,MessageInbound> exitUser = InitServlet.getSocketList();Iterator<String> it=exitUser.keySet().iterator();String names = "";while(it.hasNext()){String key=it.next();names += key + ",";}String namesTemp = names.substring(0,names.length()-1);return namesTemp;}public static void broadcastAll(String message){Set<Map.Entry<String,MessageInbound>> set = InitServlet.getSocketList().entrySet();WsOutbound outbound = null;for(Map.Entry<String,MessageInbound> messageInbound: set){try {outbound = messageInbound.getValue().getWsOutbound();outbound.writeTextMessage(CharBuffer.wrap(message));outbound.flush();} catch (Exception e) {e.printStackTrace();}}}@Overridepublic int getReadTimeout() {return 0;}}

改动也比较大,主要在onOpen那里,用户成功登录,要添加map里,同时将用户的列表以消息的方式推送给前台,消息的类型为“user”,前台会自动将用户姓名更新到每个用户聊天页面的select里。

用户的成功登录之后会将姓名(id)和对应的MyMessageInbound对象存在map里,只要找对fromName和toName,就能完成(聊天)推送的功能。

对了,这里要注意CharBuffer.wrap(message)的用法作为一个缓冲信息的用法, 用一次就清空了!

一个人的旅行,反而会更贴近自己的内心,

HTML5 WebSocket+Tomcat实现真●Web版即时聊天室(单人+多人)

相关文章:

你感兴趣的文章:

标签云: