# spring-websocket接入文档 > 本次是第二次接入spring-websocket到项目。此次接入遇到的问题与上一次完全不一样。 > ### 本次接入要点的前端说明 > 前端会判断当前浏览器是否支付websocket,支持的话,使用原生服务连接; 不支持的话采用sockjs库。 ### 服务器端要点说明 > 为了区分前端是否采用原生库的服务创建websocket,所以配置了两个Mapping-url. ## 前端相关 1. 前端首先判断当前使用平台的http协议类型(http OR https)。对应websocket的ws 和 wss。 2. 判断当前浏览器的websocket原生库类型(其实是浏览器分类),支持的用原生库,不支持的用sockjs库。 3. 编写websocket数据通信事件的默认实现。 - 前端的代码 var ws = null, ws_uri = "/sba/ws/srv"; // /sba是spring-mvc的拦截前缀。 /** websocket */ function initWebSocket(){ var ws_pre = "ws://" + window.location.host; var protocolStr = document.location.protocol; if(protocolStr == "https:") { ws_pre = "wss://" + window.location.host; } //判断当前浏览器是否支持WebSocket。浏览器的原生ws组件,没有心跳机制,默认是5分钟超时,具体需要参照http代理的超时配置。 if ('WebSocket' in window) { ws = new WebSocket(ws_pre + ws_uri); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(ws_pre + ws_uri); } else { // 有心跳协议,可以一直保持连接。 ws_uri = "/sba/ws/sockjs"; if(protocolStr == "https:") { ws = new SockJS("https://"+window.location.host + ws_uri); } else { ws = new SockJS("http://"+window.location.host + ws_uri); } } ws.onopen = function () { alert("WS服务已开启。"); };   //这个事件是接受后端传过来的数据 ws.onmessage = function (event) { //根据业务逻辑解析数据 var data = JSON.parse(event.data); alert(data); }; ws.onclose = function (event) { alert("WS服务已关闭."); }; ws.onerror = function (event) { alert("WS服务出现异常:" + +event.data); }; } ## 服务器端相关 1. 配置spring-websocket,接入spring的上下文(将webskocket配置文件import到sping 的配置文件里)。 2. 实现spring-websocket握手和协议升级的拦截器(HttpSessionHandshakeInterceptor)。将httpsession的用户标识与websocket会话关联. 3. 实现spring-websocket的消息处理器(TextWebSocketHandler)。 4. 如果使用了权限控制,应对 /ws/srv 与 /ws/sockjs 进行访问控制。 5. com.jahelai.ws 是项目的前缀包名。 ### spring-websocket的配置文件 ### WsHandshakeInterceptor import java.util.Map; import javax.servlet.http.HttpSession; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; public class WsHandshakeInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { ///获取请求参数,首先我们要获取HttpServletRequest对象才能获取请求参数;当ServerHttpRequset的层次结构打开后其子类可以获取到我们想要的http对象,那么就简单了。 //我这里是把获取的请求数据绑定到session的map对象中(attributes) ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpSession session = servletRequest.getServletRequest().getSession(false); if (session != null) { String userName = (String) session.getAttribute("SESSION_USERNAME"); if(userName == null){ userName = "WEBSOCKET_USERNAME_IS_NULL"; } // httpsession的用户标识与websocket的WebSocketSession建立关联。 attributes.put("username", session.getAttribute("username")); } return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); } } ### WsMesssageHandler import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; /** * ws服务的消息处理器。 * 接入spring-websocket的步骤: * 1。配置ws的url,开发消息处理器,协议升级处理器 * 2。将配置文件加入到spring的上下文。 * 3。 spring-security开放ws的url校验 * 4。开发前端的连接,消息处理。 * @author jahe.lai * */ public class WsMesssageHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { super.afterConnectionEstablished(session); // username=session.getAttributes().get("username").toString() // 将WebSocketSession与用户的标识关联,以供调用。可以Map WsSessionManager.addOnline(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { super.handleTextMessage(session, message); // Todo 你对交互消息的处理写在这里。 } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { super.afterConnectionClosed(session, status); WsSessionManager.remove(session); } } ## nginx代理websocket. 见: http://nginx.org/en/docs/http/websocket.html