HTML5 WebSocket+Tomcat8实现真●Web版即时聊天室(单人+多人)
程序员文章站
2022-05-01 18:39:55
之前做了一篇tomcat7的websocket聊天室,这是基于tomcat7和jdk1.7下的,有的项目是在tomcat8下的,这个时候就会有问题,因为8下面不支持那种写法,它是以...
之前做了一篇tomcat7的websocket聊天室,这是基于tomcat7和jdk1.7下的,有的项目是在tomcat8下的,这个时候就会有问题,因为8下面不支持那种写法,它是以注解的方式来实现websocket,参照HTML5 WebSocket+Tomcat实现Web版即时聊天室 ,下面就介绍一下如何在8下面实现聊天室,多人加单人!
最重要的是获取每个用户登录的session,这里的session是HttpSession,websocket自带了session,但在实际项目中我们可能只用到第一种,如何在8下面获取呢?
这里要写个类,来继承ServerEndpointConfig.Configurator:
package com.socket; import javax.websocket.HandshakeResponse; import javax.websocket.server.HandshakeRequest; import javax.websocket.server.ServerEndpointConfig; import javax.servlet.http.HttpSession; public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator { @Override public void modifyHandshake(ServerEndpointConfig config,HandshakeRequest request, HandshakeResponse response) { HttpSession httpSession = (HttpSession) request.getHttpSession(); config.getUserProperties().put(HttpSession.class.getName(), httpSession); } }
再在websocket服务里添加这个配置,就像这样
@ServerEndpoint(value = /websocket,configurator=GetHttpSessionConfigurator.class)
我将两个HttpSession放在一个map里,由用户进入,就put进去,如下
private static final Map onlineUsers = new HashMap();
代码为
package com.socket; 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 utils.MessageUtil; @ServerEndpoint(value = /websocket,configurator=GetHttpSessionConfigurator.class) public class ChatServlet { private static final Map onlineUsers = new HashMap(); private static int onlineCount = 0; private HttpSession httpSession; private Session session; @OnOpen public void onOpen(Session session,EndpointConfig config){ this.session = session; this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName()); if(httpSession.getAttribute(user) != null){ onlineUsers.put(httpSession, this); } String names = getNames(); String content = MessageUtil.sendContent(MessageUtil.USER,names); broadcastAll(content); addOnlineCount(); //在线数加1 System.out.println(有新连接加入!当前在线人数为 + onlineUsers.size()); } @OnClose public void onClose(){ onlineUsers.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println(有一连接关闭!当前在线人数为 + getOnlineCount()); } @OnMessage public void onMessage(String message, Session session) throws IOException { HashMap messageMap = MessageUtil.getMessage(message); //处理消息类 String fromName = messageMap.get(fromName); //消息来自人 的userId String toName = messageMap.get(toName); //消息发往人的 userId String mapContent = messageMap.get(content); if(toName.isEmpty()){ sendOffLine(fromName,toName); return; } if(all.equals(toName)){ String msgContentString = fromName + 对所有人说: + mapContent; //构造发送的消息 String content = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString); broadcastAll(content); }else{ try { String content = MessageUtil.sendContent(MessageUtil.MESSAGE,mapContent); singleChat(fromName,toName,content); } catch (IOException e) { e.printStackTrace(); } } System.out.println(来自客户端的消息: + message); broadcastAll(message); } private void singleChat(String fromName, String toName, String mapContent) throws IOException { String msgContentString = fromName + 对 + toName + 说: + mapContent; String contentTemp = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString); boolean isExit = false; for (HttpSession key : onlineUsers.keySet()) { if(key.getAttribute(user).equals(toName)){ isExit = true; } } if(isExit){ for (HttpSession key : onlineUsers.keySet()) { if(key.getAttribute(user).equals(fromName) || key.getAttribute(user).equals(toName)){ onlineUsers.get(key).session.getBasicRemote().sendText(contentTemp); } } }else{ String content = MessageUtil.sendContent(MessageUtil.MESSAGE,客服不在线请留言...); broadcastAll(content); } } private void sendOffLine(String fromName, String toName) throws IOException { String msgContentString = toName + 不在线; String content = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString); for (HttpSession key : onlineUsers.keySet()) { if(key.getAttribute(user).equals(fromName) || key.getAttribute(user).equals(toName)){ onlineUsers.get(key).session.getBasicRemote().sendText(content); } } } private static void broadcastAll(String msg) { for (HttpSession key : onlineUsers.keySet()) { try { onlineUsers.get(key).session.getBasicRemote().sendText(msg); } catch (IOException e) { e.printStackTrace(); } } } @OnError public void onError(Session session, Throwable error){ System.out.println(发生错误); error.printStackTrace(); } private String getNames() { String names = ; for (HttpSession key : onlineUsers.keySet()) { String name = (String) key.getAttribute(user); names += name + ,; } String namesTemp = names.substring(0,names.length()-1); return namesTemp; } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { ChatServlet.onlineCount++; } public static synchronized void subOnlineCount() { ChatServlet.onlineCount--; } }
前台的页面没有改变,经测试,可行!!!