• 第49月第6天 spring websocket实现前后端通信


    1.

    步骤二:编辑SpringWebSocketConfig,根据spring文档,编写websocketConfig,这里可参看文档,xml配置和使用注解两种方式,我选择注解方式
    
    registerWebSocketHandlers:这个方法是向spring容器注册一个handler地址,我把他理解成requestMapping
    
    addInterceptors:拦截器,当建立websocket连接的时候,我们可以通过继承spring的HttpSessionHandshakeInterceptor来搞事情。
    
    setAllowedOrigins:跨域设置,*表示所有域名都可以,不限制, 域包括ip:port, 指定*可以是任意的域名,不加的话默认localhost+本服务端口
    
    withSockJS: 这个是应对浏览器不支持websocket协议的时候降级为轮询的处理。
    
    @Configuration
    @EnableWebSocket
    public class SpringWebSocketConfig implements WebSocketConfigurer {
        
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(webSocketHandler(),"/websocket/socketServer")
                    .addInterceptors(new SpringWebSocketHandlerInterceptor()).setAllowedOrigins("*");
            
            registry.addHandler(webSocketHandler(), "/sockjs/socketServer").setAllowedOrigins("http://localhost:28180")
                   .addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
        }
     
        @Bean
        public TextWebSocketHandler webSocketHandler(){
     
            return new SpringWebSocketHandler();
        }
     
    }
    步骤三:编写SpringWebSocketHandlerInterceptor
    
    这个是创建websocket连接是的拦截器,记录建立连接的用户的session以便根据不同session来通信
    
    public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                                       Map<String, Object> attributes) throws Exception {
            System.out.println("Before Handshake");
            if (request instanceof ServletServerHttpRequest) {
                ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
                HttpSession session = servletRequest.getServletRequest().getSession(false);
                if (session != null) {
                    //使用userName区分WebSocketHandler,以便定向发送消息
                    String userName = (String) session.getAttribute("SESSION_USERNAME");  //一般直接保存user实体
                    if (userName!=null) {
                        attributes.put("WEBSOCKET_USERID",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);
        }
     
    }
    步骤四:编写SpringWebSocketHandler 
    
    public class SpringWebSocketHandler extends TextWebSocketHandler {
        
     
        private static final Map<String, WebSocketSession> users;  //Map来存储WebSocketSession,key用USER_ID 即在线用户列表
     
        //用户标识
        private static final String USER_ID = "WEBSOCKET_USERID";   //对应监听器从的key
     
     
        static {
            users =  new HashMap<String, WebSocketSession>();
        }
     
        public SpringWebSocketHandler() {}
     
        /**
         * 连接成功时候,会触发页面上onopen方法
         */
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
     
            System.out.println("成功建立websocket连接!");
            String userId = (String) session.getAttributes().get(USER_ID);
            users.put(userId,session);
            System.out.println("当前线上用户数量:"+users.size());
     
            //这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户
            //TextMessage returnMessage = new TextMessage("成功建立socket连接,你将收到的离线");
            //session.sendMessage(returnMessage);
        }
     
        /**
         * 关闭连接时触发
         */
        public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
            String userId= (String) session.getAttributes().get(USER_ID);
            System.out.println("用户"+userId+"已退出!");
            users.remove(userId);
            System.out.println("剩余在线用户"+users.size());
        }
     
        /**
         * js调用websocket.send时候,会调用该方法
         */
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
     
            super.handleTextMessage(session, message);
     
            /**
             * 收到消息,自定义处理机制,实现业务
             */
            System.out.println("服务器收到消息:"+message);
     
            if(message.getPayload().startsWith("#anyone#")){ //单发某人
     
                 sendMessageToUser((String)session.getAttributes().get(USER_ID), new TextMessage("服务器单发:" +message.getPayload())) ;
     
            }else if(message.getPayload().startsWith("#everyone#")){
     
                 sendMessageToUsers(new TextMessage("服务器群发:" +message.getPayload()));
     
            }else{
     
            }
     
        }
     
        public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
            if(session.isOpen()){
                session.close();
            }
            System.out.println("传输出现异常,关闭websocket连接... ");
            String userId= (String) session.getAttributes().get(USER_ID);
            users.remove(userId);
        }
     
        public boolean supportsPartialMessages() {
     
            return false;
        }
     
     
        /**
         * 给某个用户发送消息
         *
         * @param userId
         * @param message
         */
        public void sendMessageToUser(String userId, TextMessage message) {
            for (String id : users.keySet()) {
                if (id.equals(userId)) {
                    try {
                        if (users.get(id).isOpen()) {
                            users.get(id).sendMessage(message);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
     
        /**
         * 给所有在线用户发送消息
         *
         * @param message
         */
        public void sendMessageToUsers(TextMessage message) {
            for (String userId : users.keySet()) {
                try {
                    if (users.get(userId).isOpen()) {
                        users.get(userId).sendMessage(message);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
     
    }
    步骤五:配置文件扫描config类  我的SpringWebSocketConfig配置在包com.thunisoft.config下
    
        <context:component-scan base-package="com.thunisoft.ssm.controller,com.thunisoft.config"></context:component-scan>

    https://blog.csdn.net/runbat/article/details/80985944

  • 相关阅读:
    dotnet 使用 MessagePack 序列化对象
    dotnet 使用 MessagePack 序列化对象
    PHP die() 函数
    PHP defined() 函数
    PHP define() 函数
    PHP constant() 函数
    PHP connection_status() 函数
    查看物理CPU个数、核数、逻辑CPU个数
    CF997C Sky Full of Stars
    dotnet 使用 lz4net 压缩 Stream 或文件
  • 原文地址:https://www.cnblogs.com/javastart/p/13773920.html
Copyright © 2020-2023  润新知