spring 配置:
<bean id="websocket" class="com.xianlaohu.yao.controller.socket.SocketHandler"/> <websocket:handlers> <websocket:mapping path="/room/chat" handler="websocket"/> <websocket:handshake-interceptors> <bean class="com.xianlaohu.yao.controller.socket.HandshakeInterceptor"/> </websocket:handshake-interceptors> </websocket:handlers>
依赖包:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency>
nginx 配置
upstream home-dev-ws{
server IP: port;
}
#websocket 需要加下这个
map $http_upgrade $connection_upgrade {
default upgrade;
‘‘ close;
}
server {
listen 80;
server_name xxxxx.com
rewrite ^(.*)/__dev/?$ /__dev/;
if ( $http_cookie ~* "(.*)$")
{
set $user_cookie $1;
}
location /room/chat {
proxy_pass http://home-dev-ws;
proxy_redirect off;
proxy_read_timeout 43200;
keepalive_timeout 600; # 链接保持的时间
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
socket 链接已经信息处理handler:
public class SocketHandler extends TextWebSocketHandler { private final static Logger logger = LoggerFactory.getLogger(SocketHandler.class); private static Map<String, UserWebSocketSession> users= new HashMap<>(); //所有在线用户 private static Map<String, Set<String>> rooms = new HashMap<>(); //所有房间 private final static String roomId = "12345"; /** * 在UI在用js调用websocket.send()时候,会调用该方法 */ @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { super.handleTextMessage(session, message); UserWebSocketSession userWebSocketSession = users.get(session.getId()); if(userWebSocketSession != null && userWebSocketSession.getRoomId() != null){ Set<String> room = rooms.get(userWebSocketSession.getRoomId()); logger.info("----12---room:{}"+ JsonUtil.toJSON(room)); if(room == null || room.size() <= 0){ return; } sendMessageToUsers(session, room, message); logger.info("----------1"); }else { logger.error("current_user could not send messege userWebSocketSession:{}", JsonUtil.toJSON(userWebSocketSession)); } } /** * 连接成功时候,会触发UI上onopen方法 */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { if(users.get(session.getId()) == null){ UserWebSocketSession userWebSocketSession = new UserWebSocketSession(); userWebSocketSession.setRoomId(roomId); userWebSocketSession.setSession(session); users.put(session.getId(), userWebSocketSession); Set<String> room = rooms.get(roomId); if(room == null){ room = new HashSet<>(); rooms.put(roomId, room); } logger.info("----====-----rooms:{}" + JsonUtil.toJSON(rooms)); room.add(session.getId()); logger.info("---------------room:{}" + JsonUtil.toJSON(room)); logger.info("new user ====session_id:{}", session.getId()); } logger.info("connect to the websocket success..... ."); } /** * Handle an error from the underlying WebSocket message transport. * @param session * @param exception * @throws Exception */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { UserWebSocketSession userSession= users.get(session.getId()); if(userSession == null){ return; } Set<String> room = rooms.get(userSession.getRoomId());//查找所在房间 room.remove(session.getId());//从房间中去除 if(room.size() <=0){ //房间没人,清除房间 rooms.remove(userSession.getRoomId()); } users.remove(session.getId());//从在线用户列表里移除 logger.info("websocket connection closed......"); } /** * Invoked after the WebSocket connection has been closed by either side, * or after a transport error has occurred. Although the session may technically still be open, * depending on the underlying implementation, sending messages at this point is discouraged and most likely will not succeed. * @param session * @param closeStatus * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) { logger.info("----close---11-closeStatus:{} session-status:{}__ user_lise:{}", JsonUtil.toJSON(closeStatus), session.isOpen(), users.size()); UserWebSocketSession userSession= users.get(session.getId()); if(userSession == null){ return; } Set<String> room = rooms.get(userSession.getRoomId());//查找所在房间 room.remove(session.getId()); //从房间中去除 if(room.size() <=0){ //房间没人,清除房间 rooms.remove(userSession.getRoomId()); } users.remove(session.getId()); //从在线用户列表里移除 logger.info("----------1111_ user_size:{}"+users.size() ); } /* Whether the WebSocketHandler handles partial messages. If this flag is set to true and the underlying WebSocket server supports partial messages, then a large WebSocket message, or one of an unknown size may be split and maybe received over multiple calls to WebSocketHandler.handleMessage(WebSocketSession, WebSocketMessage). The flag WebSocketMessage.isLast() indicates if the message is partial and whether it is the last part. */ @Override public boolean supportsPartialMessages() { logger.info("websocket connection supportsPartialMessages......"); return false; } /** * 给某个用户发送消息 * @param currentSession * @param message */ public void sendMessageToUsers(WebSocketSession currentSession, Set<String> sessionIdSet, TextMessage message) { logger.info("currentSession_id:{}=======sessionIdSet:{}", currentSession.getId(), sessionIdSet.size()); Iterator<String> iterator = sessionIdSet.iterator(); while (iterator.hasNext()) { String sessionId = iterator.next(); if(sessionId.equals(currentSession.getId())){//信息不发给自己 continue; } UserWebSocketSession user = users.get(sessionId); String fromUserName = user.getUserName(); WebSocketSession userSession = user.getSession(); logger.info("-send to--session_id:{}, user_name:{}", userSession.getId(), fromUserName); if (!userSession.equals(currentSession)) { if (userSession.isOpen()) { sendMessageToUser(userSession, fromUserName, message); } } } } /** * 给某个用户发送消息 * * @param message */ public void sendMessageToUser(WebSocketSession userSession, String userName, TextMessage message) { logger.info("======send message to session_id:{}: name:{}", userSession.getId(), userName); if(userSession != null && userSession.isOpen()){ TextMessage returnMessage = new TextMessage(new DateTime().toString("HH:mm:ss")+"/<br>"+(userName != null? userName:"")+" "+message.getPayload()); try { userSession.sendMessage(returnMessage); } catch (IOException e) { e.printStackTrace(); } } } }
拦截器:
HandshakeInterceptor
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { boolean b = super.beforeHandshake(request, response, wsHandler, attributes); System.out.println("Before Handshake=====:"+ b); return b; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); System.out.println("after Handshake=====: 1"); } }
交互界面------
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!doctype html> <html> <head> <title>WebSocket/SockJS Echo Sample (Adapted from Tomcat‘s echo sample)</title> <style type="text/css"> #connect-container { float: left; width: 400px } #connect-container div { padding: 5px; } #console-container { float: left; margin-left: 15px; width: 400px; } #console { border: 1px solid #CCCCCC; border-right-color: #999999; border-bottom-color: #999999; height: 170px; overflow-y: scroll; padding: 5px; width: 100%; } #console p { padding: 0; margin: 0; } </style> <%--<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>--%> <script type="text/javascript"> var ws = null; var url = null; var transports = []; function setConnected(connected) { document.getElementById(‘connect‘).disabled = connected; document.getElementById(‘disconnect‘).disabled = !connected; document.getElementById(‘echo‘).disabled = !connected; } function connect() { alert("url:"+url); if (!url) { alert(‘Select whether to use W3C WebSocket or SockJS‘); return; } ws = (url.indexOf(‘sockjs‘) != -1) ? new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url); ws.onopen = function () { setConnected(true); log(‘Info: connection opened.‘); }; ws.onmessage = function (event) { // log(‘Received: ‘ + event.data); log(event.data); }; ws.onclose = function (event) { setConnected(false); log(‘Info: connection closed.‘); log(event); }; } function disconnect() { if (ws != null) { ws.close(); ws = null; } setConnected(false); } function echo() { if (ws != null) { var message = document.getElementById(‘message‘).value; // log(‘Sent: ‘ + message); log( message); ws.send(message); } else { alert(‘connection not established, please connect.‘); } } function updateUrl(urlPath) { if (urlPath.indexOf(‘sockjs‘) != -1) { url = urlPath; document.getElementById(‘sockJsTransportSelect‘).style.visibility = ‘visible‘; } else { if (window.location.protocol == ‘http:‘) { url = ‘ws://‘ + window.location.host + urlPath; } else { url = ‘wss://‘ + window.location.host + urlPath; } document.getElementById(‘sockJsTransportSelect‘).style.visibility = ‘hidden‘; } } function updateTransport(transport) { alert(transport); transports = (transport == ‘all‘) ? [] : [transport]; } function log(message) { var console = document.getElementById(‘console‘); var p = document.createElement(‘p‘); p.style.wordWrap = ‘break-word‘; p.appendChild(document.createTextNode(message)); console.appendChild(p); while (console.childNodes.length > 25) { console.removeChild(console.firstChild); } console.scrollTop = console.scrollHeight; } </script> </head> <body> <noscript> <h2 style="color: #ff0000">Seems your browser doesn‘t support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!</h2> </noscript> <div> <div id="connect-container"> <input id="radio1" type="radio" name="group1" onclick="updateUrl(‘/room/chat‘);"> <label for="radio1">W3C WebSocket</label> <br> <input id="radio2" type="radio" name="group1" onclick="updateUrl(‘/room/chat‘);"> <label for="radio2">SockJS</label> <div id="sockJsTransportSelect" style="visibility:hidden;"> <span>SockJS transport:</span> <select onchange="updateTransport(this.value)"> <option value="all">all</option> <option value="websocket">websocket</option> <option value="xhr-polling">xhr-polling</option> <option value="jsonp-polling">jsonp-polling</option> <option value="xhr-streaming">xhr-streaming</option> <option value="iframe-eventsource">iframe-eventsource</option> <option value="iframe-htmlfile">iframe-htmlfile</option> </select> </div> <div> <button id="connect" onclick="connect();">进入房间</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">退出房间</button> </div> <div> <textarea id="message" style="width: 350px">Here is a message!</textarea> </div> <div> <button id="echo" onclick="echo();" disabled="disabled">发送</button> </div> </div> <div id="console-container"> <div id="console"></div> </div> </div> </body> </html>
时间: 2024-10-14 05:20:49