Spring整合WebSocket实现服务端推送消息给客户端


1、pom.xml额外增加依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>

2、自定义JoyinMessageHandler继承WebSocketHandler,处理消息

/*
 * 文件名:JoyinMessageHandler.java
 * 版权:Copyright 2016-2017 JoyinTech. Co. Ltd. All Rights Reserved.
 * 描述:中信银行资管系统
 * 修改人:Administrator
 * 修改时间:2020年1月16日
 * 修改内容:新建
 * 系统名称:中信银行资管系统
 */

package com.joyintech.tams.framework;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

/**
 * 〈一句话功能简述〉 〈功能详细描述〉
 * 
 * @author Administrator
 * @version 1.0 2020年1月16日
 * @see JoyinMessageHandler
 * @since 1.0
 */
@Component
public class JoyinMessageHandler implements WebSocketHandler {

    /**
     * 用户
     */
    public static final String USER_KEY = "socket_user";

    /**
     * 用户数量
     */
    private final static int size = 300;

    /**
     * userMap:存储用户连接webscoket信息
     * 
     * @since JDK 1.7
     */
    private final static Map<String, WebSocketSession> userMap;
    static {
        userMap = new ConcurrentHashMap<String, WebSocketSession>(size);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status)
        throws Exception {
        String userId = this.getUserId(session);
        if (!StringUtils.isEmpty(userId)) {
            userMap.remove(userId);
            System.err.println(userId + "用户已成功关闭会话");
        }
        else {
            System.err.println("关闭时,获取用户id为空");
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session)
        throws Exception {
        String userId = this.getUserId(session);
        if (!StringUtils.isEmpty(userId)) {
            userMap.put(userId, session);
        }
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message)
        throws Exception {
        String msg = message.toString();
        String userId = this.getUserId(session);
        System.err.println("该" + userId + "用户发送的消息是:" + msg);
        message = new TextMessage("服务端已经接收到消息,msg=" + msg);
        session.sendMessage(message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable e)
        throws Exception {
        WebSocketMessage<String> message = new TextMessage("异常信息:" + e.getMessage());
        session.sendMessage(message);
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    private String getUserId(WebSocketSession session) {
        try {
            String userId = (String)session.getAttributes().get(USER_KEY);
            return userId;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 给某个用户发送消息
     *
     * @param userId
     * @param message
     */
    public void sendMessageToUser(String userId, TextMessage message) {
        WebSocketSession webSocketSession = userMap.get(userId);
        if (webSocketSession != null && webSocketSession.isOpen()) {
            try {
                webSocketSession.sendMessage(message);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3、编写拦截器WebSocketInterceptor继承HttpSessionHandshakeInterceptor实现用户的绑定

/*
 * 文件名:WebSocketInterceptor.java
 * 版权:Copyright 2016-2017 JoyinTech. Co. Ltd. All Rights Reserved.
 * 描述:中信银行资管系统
 * 修改人:Administrator
 * 修改时间:2020年1月16日
 * 修改内容:新建
 * 系统名称:中信银行资管系统
 */

package com.joyintech.tams.framework.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.support.HttpSessionHandshakeInterceptor;

import com.joyintech.tams.framework.JoyinMessageHandler;

/**
 * 〈一句话功能简述〉 〈功能详细描述〉
 * 
 * @author Administrator
 * @version 1.0 2020年1月16日
 * @see WebSocketInterceptor
 * @since 1.0
 */
public class WebSocketInterceptor extends HttpSessionHandshakeInterceptor {

    /**
     * TODO 描述该方法的实现功能.
     * 
     * @see org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor#beforeHandshake(org.springframework.http.server.ServerHttpRequest,
     *      org.springframework.http.server.ServerHttpResponse,
     *      org.springframework.web.socket.WebSocketHandler, java.util.Map)
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                   WebSocketHandler wsHandler, Map<String, Object> attributes)
        throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest)request;
            // 获取参数
            String userId = serverHttpRequest.getServletRequest().getParameter("userId");
            attributes.put(JoyinMessageHandler.USER_KEY, userId);
        }

        return true;
    }
}

4、修改spring配置文件,增加以下配置

<!-- 配置webSockte -->
    <websocket:handlers allowed-origins="*">
    <!-- 前端握手请求地址 -->
        <websocket:mapping path="/socketServer" handler="joyinMessageHandler"/>
        <websocket:handshake-interceptors>
            <bean class="com.joyintech.tams.framework.interceptor.WebSocketInterceptor"/>
        </websocket:handshake-interceptors>
    </websocket:handlers>

5、修改js增加以下方法

var homepage = function() {
    return {
        /**
         * 绑定用户信息
         */
        bindUserInfo : function() {
            if('WebSocket' in window) {
                var websocket = new WebSocket("ws://"+baseFullPath+"socketServer?userId="+loginUserId);
                // 打开连接时
                websocket.onopen = function(evnt) {
                    console.log("websocket已启用");
                };
                
                // 收到消息时
                websocket.onmessage = function(message) {
                    console.log("收到websocket消息:" + message.data);
                };
                
                //出错时
                websocket.onerror = function(evnt) {
                    console.log("与后台握手出现问题!");
                };
                
                //关闭时
                websocket.onclose = function(evnt) {
                    console.log("正在关闭 webSocket ");
                };
            }
        },
    }
}();

jQuery(document).ready(function() {
    // 绑定用户信息
    homepage.bindUserInfo();
})

6、修改jsp获得baseFullPath

<%
    String path = request.getContextPath();
    String baseFullPath = request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<script type="text/javascript">
var baseFullPath = '<%=baseFullPath%>';
var loginUserId = '${user.userId}';
</script>

7、在任意地方调用com.joyintech.tams.framework.JoyinMessageHandler.sendMessageToUser(String, TextMessage)方法即可

messageHandler.sendMessageToUser("00000000000000000002", new TextMessage("发送消息给用户00000000000000000002"));


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM