服务器推送技术--spring websocket + 心跳保活重连 简易聊天室demo(一)

关于websocket的基本概念和应用场景都可以从网上轻松的查到,因此这里不再赘述了。使用websocket的经典demo不外乎web聊天室,因此这里记录一下使用 Spring Websocket 搭建这个demo的过程,以及关于心跳保活和断线重连的客户端实现的一点尝试。

篇幅限制以下只给出关键代码,完整代码地址:MultiClientWebChat

聊天室demo搭建

准备工作

在maven中引入spring-websocket模块:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>

模块实现

spring websocket的使用,主要就是三个部分:

  • 配置类WebSocketConfig(注册websocket接口)
  • 拦截器WebSocketInterceptor(进行握手连接)
  • 处理类SocketHandler(处理通信业务)
配置部分

websocket 的配置即是要完成websocket模块在spring中的引入和其它两个模块的注册,官网上提供了XML和config类的两种实现方式,这里采用XML风格的配置:

<context:component-scan base-package="com.firejq.websocket.handler,com.firejq.websocket.handshake"/>

<websocket:handlers allowed-origins="*">
    <websocket:mapping path="/messageHandler" handler="messageHandler"/>
    <websocket:handshake-interceptors>
        <bean class="com.firejq.websocket.handshake.WebsocketHandshake"/>
    </websocket:handshake-interceptors>
</websocket:handlers>

<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
    <property name="maxTextMessageBufferSize" value="8192"/>
    <property name="maxBinaryMessageBufferSize" value="8192"/>
</bean>

<bean id="messageHandler" class="com.firejq.websocket.handler.MessageHandler"></bean>
处理器部分

处理器部分的工作是在websocket握手完毕后,对连接的具体业务逻辑以及连接中断和出错等事件进行操作。

    //连接队列
    private static final List<WebSocketSession> sessions = new ArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        //加入连接队列
        sessions.add(webSocketSession);

        webSocketSession.sendMessage(new TextMessage("你与服务器连接成功了!你的sessionID为【" + webSocketSession.getId() + "】"));

        StringBuilder sessionIds = new StringBuilder("");
        for (WebSocketSession session : sessions) {
            session.sendMessage(new TextMessage("用户" + webSocketSession.getId() + "已加入聊天室"));
            sessionIds.append(" " + session.getId() + " ");
        }

        System.out.println("一个客户端连接上了服务器!webSocketSessionId为【" + webSocketSession.getId() + "】, 当前服务器session队列中有:【" + sessionIds + "】");

        webSocketSession.sendMessage(new TextMessage("当前聊天室有id为【" + sessionIds + "】的用户"));
    }


    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        Object payload = webSocketMessage.getPayload();
        if (payload instanceof String) {
            System.out.println("服务器收到来自sessionId【" + webSocketSession.getId() + "】的信息:【" + payload + "】");

            this.sendToAll("用户" + webSocketSession.getId() + "说: 【" + payload + "】");
        }

    }
握手拦截部分
public class MyHandShake implements HandshakeInterceptor {

    /** 
      * 初次握手前,若返回false,则不建立链接 
      */
    // 可在此处将HttpSession中对象放入WebSocketSession中,便于之后Handler使用HttpSession
    // 也可直接使用内建拦截器HttpSessionHandshakeInterceptor,它可以传递HTTP session attributes到WebSocket session中
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        //. . .
        return true;
    }

    /** 初次握手访问后 */
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
    }

}
客户端实现
        var websocket = null;

        if (window.WebSocket && window.WebSocket.prototype.send) {
            websocket = new WebSocket(url);
        }

        websocket.onopen = function (event) {
            document.getElementById("state-info").innerHTML = "连接成功";
            console.log("Connected to WebSocket server.");

            document.getElementById("chat").onkeydown = function(KeyboardEvent) {
                if (KeyboardEvent.keyCode == 13) {//按下ENTER键时触发向服务器发送消息

                    var message = document.getElementById('chat').value;
                    if (message !== "") {
                        websocket.send(message);
                        document.getElementById('chat').value = '';
                    }

                }
            };

        websocket.onmessage = function(message) {
            console.log("client received a message.data: " + message.data);
            output.log(message.data);
        };

        //窗口关闭前,主动关闭websocket连接
        window.onbeforeunload = function () {
            websocket.close();
        };


        /**
         * 信息输出容器output
         * @type {{}}
         */
        var output = {};
        output.log = (function(message) {
            var op = document.getElementById('output');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.innerHTML = message;
            op.appendChild(p);
            while (op.childNodes.length > 25) {
                op.removeChild(op.firstChild);
            }
            op.scrollTop = op.scrollHeight;
        });

        /**
         * 执行入口
         * @type {string}
         */
        var url = "ws://127.0.0.1:8080/messageHandler";
        connect(url);

完整代码地址:MultiClientWebChat

猜你喜欢

转载自blog.csdn.net/jqsad/article/details/76359443