Spring集成WebSocket

  • Post author:
  • Post category:其他


WebSocket协议主要用来实现后台服务端主动向客户端推送消息,当然,协议本身支持双向通信。

在Spring项目中集成WebSocket还是比较简单的,但是WebSocket的Session和HttpSession并不相通,如果想获取HttpSession中的登录用户就要稍费工夫,因此,记录成篇。




一、集成WebSocket

  1. 项目添加依赖包:

    <!-- SpringBoot Websocket -->
    <dependency>  
       <groupId>org.springframework.boot</groupId>  
       <artifactId>spring-boot-starter-websocket</artifactId>  
    </dependency>
    
  2. 增加WebSocketConfig配置类:

    /**
     * websocket 配置
     *
     * @author xhp
     */
    @Configuration
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
    }
    
  3. 编写WebSocketSever类:

    @Component
    @ServerEndpoint(value = "/ws/message")
    public class WebSocketServer {
    
        /**
         * 连接建立成功调用的方法
         */
        @OnOpen
        public void onOpen(Session session) throws Exception {
            
        }
    
        /**
         * 连接关闭时处理
         */
        @OnClose
        public void onClose(Session session) {
        
        }
    
        /**
         * 抛出异常时处理
         */
        @OnError
        public void onError(Session session, Throwable exception) throws Exception {
            if (session.isOpen()) {
                // 关闭连接
                session.close();
            }
        }
    
        /**
         * 服务器接收到客户端消息时调用的方法
         */
        @OnMessage
        public void onMessage(String message, Session session) {
    
        }
    
    }
    
  4. 编写html页面,测试连接:

    <script type="text/javascript">
        $(document).ready(function(){
        	// WebSocket
    		var wsBaseUrl = /*[[${"ws://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]*/'';
    		var ws = new WebSocket(wsBaseUrl + '/ws/message');
    		ws.onopen = function (event) {
    			console.log('WS已打开连接');
    		}
    		ws.onmessage = function (event) {
    			// TODO 接收消息
    			console.log(event.data);
    		}
    		ws.onclose = function (event) {
    			console.log('WS已关闭连接');
    		}
    
            // 发送消息
            $('#btn_send').click(function() {
                var message = $('#message').val();
                if (ws) {
                    ws.send(message);
                } else {
                    alert("未连接到服务器");
                }
            });
            //断开
            $('#btn_exit').click(function() {
                if (ws) {
                    ws.close();
                    ws = null;
                }
            });
        })
    </script>
    



二、WebSocket会话获得登录用户

  1. 场景说明:

    • 项目中常见场景,需要给某个用户或者某类用户推送消息;
    • 我们需要在全部的WebSocket连接会话里根据登录用户匹配有效的发送会话;
    • 因为WebSocket的Session和HttpSession是相互独立的,本身没用对应关系,那么,我们只能想办法把需要的信息放到Session里。
  2. 修改WebSocketConfig配置类,重写其继承类的方法,将用户信息放入,示例如下:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    import javax.websocket.HandshakeResponse;
    import javax.websocket.server.HandshakeRequest;
    import javax.websocket.server.ServerEndpointConfig;
    
    /**
     * websocket 配置
     *
     * @author xhp
     */
    @Configuration
    public class WebSocketConfig extends ServerEndpointConfig.Configurator {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
        @Override
        public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
            // 将用户信息存储到socket的配置里
            sec.getUserProperties().put("sysUser", ShiroUtils.getSysUser());
            super.modifyHandshake(sec, request, response);
        }
    }
    
  3. 修改WebSocketServer类,读取用户信息,示例如下:

    /**
     * websocket 消息处理
     *
     * @author xhp
     */
    @Component
    @ServerEndpoint(value = "/ws/message", configurator = WebSocketConfig.class)
    public class WebSocketServer {
    
        /**
         * 连接建立成功调用的方法
         */
        @OnOpen
        public void onOpen(Session session) throws Exception {
    		// 读取用户信息
    		SysUser sysUser= (SysUser)session.getUserProperties().get("sysUser");
    
        }
    }
    



三、注意事项

  1. 本示例项目是Springboot,如果项目是Spring而非Springboot,那么第一步的依赖包有所不同,后面的步骤是一致的;

  2. WebSocketServer

    类的类注解需要增加对配置文件的引入

    configurator = WebSocketConfig.class

    ,否则配置文件的重写方法是不生效的;



版权声明:本文为xhp312098226原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。