简单发布一个基于springMVC的websocket的实现配置,springMVC的搭建过程这里就不说明了 。只实现H5的websocket,js实现没有考虑


  • springMVC的配置文件如下:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:websocket="http://www.springframework.org/schema/websocket"
 xsi:schemaLocation="
        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/websocket 
        http://www.springframework.org/schema/websocket/spring-websocket-4.3.xsd">
        
    <!-- 连接处理的句柄,用于接收消息,推送消息,根据自己来实现需求 -->
    <bean id="systemWebSocketHandler" class="com.golden.socket.handler.SystemWebSocketHandler"/>
    <!-- allowed-origins="*" 声明支持跨域 -->
    <websocket:handlers allowed-origins="*">
            <!-- path属性就是声明websocket的服务连接点。如:访问时HTTP://ip:端口/web名称/servers.do-->
     <websocket:mapping path="/servers" handler="systemWebSocketHandler"/>  
            <websocket:handshake-interceptors>  
         <!-- 连接拦截器,用于连接之前 ,之后做下业务处理-->
            <bean class="com.golden.socket.interceptor.WebSocketInterceptor"/>  
            </websocket:handshake-interceptors> 
    </websocket:handlers>
</beans>


  • WebSocketInterceptor类,配置文件中的拦截器
package com.golden.socket.interceptor;


import java.util.Map;
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.HandshakeInterceptor;


import com.golden.socket.consts.SocketConst;


/**
 * 连接成功,会调用这个拦截器 
 */
public class WebSocketInterceptor implements HandshakeInterceptor{
 /**
  * 连接后会调用这个方法
  */
 @Override
 public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler, Exception e) {
  System.out.println("WebSocketInterceptor 执行");

 }
 /**
  * 第一次连接会调用这个方法 
  * 参数params 会自动添加到 WebSocketSession
  * loginKey 登录socket-web的标识,用于区分登录身份
  */
 @Override
 public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler,
 Map<String, Object> params) throws Exception {
  ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
  String loginKey = (String)servletRequest.getServletRequest().getParameter(SocketConst.LOGIN_KEY);
  params.put(SocketConst.LOGIN_KEY, loginKey);
         return true;
 }

}
  • SystemWebSocketHandler类, 配置文件中的systemWebSocketHandler


package com.golden.socket.handler;


import java.util.Map;


import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;


import com.golden.socket.consts.SocketConst;
import com.golden.socket.users.SocketUser;


/**
 * 消息服务类
 */
public class SystemWebSocketHandler implements WebSocketHandler {

 /**
  * 拦截器拦截第一次连接后会调用这个方法 
  * 业务实现:登录后,将用户存入缓存
  */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
     Map<String, Object> param = session.getAttributes();
     String loginKey = param.get(SocketConst.LOGIN_KEY).toString();
     SocketUser.put(loginKey, session);
    }
    /**
     * 连接的用户,通过这个方法发送消息会调用这个方法 
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
     //页面发送的消息,会传到该方法中。
    }
    /**
     * 心跳检测发现连接不上会调用这个方法,之后会调用连接关闭的方法
     * 业务实现:删除session
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
     Map<String, Object> param = session.getAttributes();
     String loginKey = param.get(SocketConst.LOGIN_KEY).toString();
     SocketUser.remove(loginKey, session);
    }
    /**
     * 关闭连接会调用这个方法 ,这个关闭会由两个地方触发,一个是浏览器主动退出,还有一个是心跳检测发现连接不上也会调用这个方法。
     * 业务实现:发送XX退出消息
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
    }
 
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
 
}
  • js 端
var MyWebSocket = function (){
 var websocket;
 if ('WebSocket' in window) {
     websocket = new WebSocket("ws://IP:端口/socket-web/servers?loginKey=sss");
 } else if ('MozWebSocket' in window) {
        websocket = new MozWebSocket("ws://IP:端口/socket-web/servers");
    }else {
     return
 }
 websocket.onopen = function (event) {
 //messageFactory.receiveMessage(JSON.parse(event.data))
 };
 websocket.onmessage = function (event) {
 $("#sysContent").html(event.data);
 if(!$("#sysMessage").is(":hidden")){
 $("#sysMessage").slideUp(1500)
 }
 $("#sysMessage").slideDown(1500);
 };
 websocket.onerror = function (event) {
 };
 websocket.onclose = function (event) {
 alert("您已被踢下线");
 };
 return websocket;
}


$(function (){
 var ws = new MyWebSocket();
 ws.send("这是我发送的方法");//这个内容会发送到 SystemWebSocketHandler类的 handleMessage方法中
})
  • WebSocketSession 类说明
这个类可以被看做是传统的web服务器的session。每次连接都会创建一个session,关闭页面就是断开了连接。再连接就会是全新的session。所以再实现功能时,要管理好自己的session.

以上是简单的通讯。具体逻辑和复杂场景需要参考很多知识点,真实场景可能要考虑消息格式的约定,可能需要登录队列,考虑线程,负载等问题。这个只是demo,用于初学者学习