首先简单介绍下WebSocket,WebSocket是HTML5中内容,是基于TCP的一种新的网络协议,它支持全双工、长连接的通信。在它出现之前,实时消息发送与接收通过轮询实现,但是频繁与服务器建立连接十分消耗资源。因此WebSocket出现了,在不断开连接的情况下,处于连接的用户可以任意发送消息,从而实现了在线聊天的功能。
因为我们JavaWeb课程作业是实现在线聊天功能,看到这题目我内心是崩溃的,不停百度,偶然发现Tomcat中自带了一个WebSocket的小例子, 有点小激动,运行一看,它竟然是群聊的。。。没办法,只好查看他的源代码,经过几天的推敲,终于看懂他的代码,并改写成一对一私聊。下面上代码
var Chat = {}; Chat.socket = null; // 创建一个websocket实例 Chat.connect = (function(host) { if ('WebSocket' in window) { Chat.socket = new WebSocket(host); } else if ('MozWebSocket' in window) { Chat.socket = new MozWebSocket(host); } else { Console.log('Console.log:你的浏览器不支持WebSocket'); return; } Chat.socket.onopen = function(){ Console.log('Console.log:WebSocket链接打开'); //按下回车键发送消息 document.getElementById('chat').onkeydown = function(event) { if (event.keyCode == 13) { Chat.sendMessage(); } }; }; Chat.socket.onclose = function () { document.getElementById('chat').onkeydown = null; Console.log('Console.log:WebSocket前端链接关闭'); }; Chat.socket.onmessage = function (message) { Console.log(message.data); }; }); Chat.initialize = function() { //链接地址选择聊天页面的URL if (window.location.protocol == 'http:') { Chat.connect("ws://" + window.location.host + "/onLineChat/index.jsp"); } else { Chat.connect("wss://" + window.location.host + "/onLineChat/index.jsp"); } }; //发送消息函数,后面动态添加了发送好友的唯一ID Chat.sendMessage = (function() { var fid = $("#hidden-fid").val(); var messageContain = document.getElementById('chat').value; var message = messageContain +"-"+fid; if(fid==""){ alert("未选择发送消息的好友!"); return; }else{ if (messageContain != "") { Chat.socket.send(message); document.getElementById('chat').value = ''; }else{ alert("发送消息不能为空!"); } } }); var Console = {}; Console.log = (function(message) { var console = document.getElementById('console'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.innerHTML = message; console.appendChild(p); console.scrollTop = console.scrollHeight; }); //初始化函数 Chat.initialize(); document.addEventListener("DOMContentLoaded", function() { var noscripts = document.getElementsByClassName("noscript"); for (var i = 0; i < noscripts.length; i++) { noscripts[i].parentNode.removeChild(noscripts[i]); } }, false);
package websocket.chat; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSession; import javax.websocket.EndpointConfig; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import com.chat.common.HTMLFilter; import com.chat.controller.UserDAOImpl; import com.chat.entity.User; @ServerEndpoint(value = "/index.jsp",configurator=GetHttpSessionConfigurator.class) public class ChatAnnotation { private static final Log log = LogFactory.getLog(ChatAnnotation.class); private static final Map
connection = new HashMap
(); private String userId; private String nickname; private Session session; public ChatAnnotation() { } @OnOpen public void start(Session session,EndpointConfig config) { //获取HttpSession对象 HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName()); User user = (User)httpSession.getAttribute("user"); String uid = user.getId(); this.nickname = user.getUsername(); this.userId = uid; this.session = session; /*判断链接是否已经在链接队列中,存在就不加*/ if(!connection.containsKey(uid)){ connection.put(uid, this); String message = "* 你已经链接"; toConfirmFriend(message,userId); } } @OnClose public void end() { connection.remove(this.userId); } @OnMessage public void incoming(String message){ String[] all = message.split("-"); //要接收消息好友的ID String uid = all[1]; //判断好友的连接是否存在,不存在就提示好友掉线 if(connection.containsKey(uid)){ String filteredMessage = String.format("%s: %s", nickname, HTMLFilter.filter(all[0].toString())); sendCommonRecord(filteredMessage,uid,this.userId); }else{ ChatAnnotation client = connection.get(uid); String mes = String.format("* %s %s", client.nickname, "已经掉线!"); //将掉线信息发给自己 toConfirmFriend(mes,this.userId); } } @OnError public void onError(Throwable t) throws Throwable { log.error("Chat Error: " + t.toString(), t); } //发送给指定的好友 private static void toConfirmFriend(String msg,String uid) { ChatAnnotation client = connection.get(uid); try { synchronized (client) { client.session.getBasicRemote().sendText(msg); } } catch (IOException e) { log.debug("Chat Error: Failed to send message to "+client.nickname, e); try { client.session.close(); } catch (IOException e1) { // Ignore } } } //给聊天的双发发共同消息 private static void sendCommonRecord(String msg,String sid,String gid) { ChatAnnotation client_send = connection.get(sid); ChatAnnotation client_get = connection.get(gid); try { synchronized (client_send) { client_send.session.getBasicRemote().sendText(msg); } //将这条聊天记录保存在数据库 UserDAOImpl userDAOImpl = new UserDAOImpl(); userDAOImpl.saveCharRecord(msg, sid, gid); } catch (IOException e) { log.debug("Chat Error: Failed to send message to "+client_send.nickname, e); connection.remove(sid); try { client_send.session.close(); }catch (IOException e1) { // Ignore } } try { synchronized (client_get) { client_get.session.getBasicRemote().sendText(msg); } } catch (IOException e) { log.debug("Chat Error: Failed to send message to "+client_get.nickname, e); connection.remove(gid); try { client_get.session.close(); } catch (IOException e1) { // Ignore } } } }
这是后台代码,使用注解方式监听前台的事件
采用HttpSession的方法在ChatAnnotation中访问session的属性
——————————————下载地址——————————————————
源码下载:百度网盘 请输入提取码
提取码: xgck
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176363.html原文链接:https://javaforall.net
