美文网首页springbootSpringboot
SpringBoot 集成 WebSocket

SpringBoot 集成 WebSocket

作者: JobanCai | 来源:发表于2019-01-20 22:56 被阅读126次

    官方地址:SpringBoot WebSockets
    原作者地址:http://www.caijp.xyz/archives/springboot-websocket


    webSocket 介绍

    WebSocket协议RFC 6455提供了一种标准化的方式来建立一个全双工,客户端和服务器之间的双向通信信道在一个TCP连接。
    WebSocket 交互始于一个HTTP请求,HTTP请求的header中携带Upgrade参数,对应的值是WebSocket,header中的Connection参数对应的值是Upgrade。

    GET /spring-websocket-portfolio/portfolio HTTP/1.1
    Host: localhost:8080
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
    Sec-WebSocket-Protocol: v10.stomp, v11.stomp
    Sec-WebSocket-Version: 13
    Origin: http://localhost:8080 
    

    服务端返回的通常不是200的状态码,而是服务端支持WebSocket的返回

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
    Sec-WebSocket-Protocol: v10.stomp
    

    然后客户端将协议升级成为WebSocket,握手完成。

    HTTP vs WebSocket

    使用HTTP与其他应用程序的交互通常通过URL,服务器将请求路由到相应的处理程序是基于HTTP URL,method,和headers。
    相比于HTTP, WebSockets通常只是有一个URL初始连接,随后所有应用程序消息流上同样的TCP连接。

    SpringBoot 集成WebSocket Demo

    1. maven 依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    

    2.WebSocketHandler

    SpringBoot 提供两种WebSocketHandler,TextWebSocketHandler 用于处理文本信息,BinaryWebSocketHandler用于处理二进制信息。session对象表示当前连接会话,session.sendMessage(new TextMessage("send message to current user"));向当前客户端发送消息

    import org.springframework.web.socket.WebSocketHandler;
    import org.springframework.web.socket.WebSocketSession;
    import org.springframework.web.socket.TextMessage;
    
    @Component
    public class MyHandler extends TextWebSocketHandler {
    
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            log.info("Opened new session in instance " + this);
        }
    
        @Override
        public void handleTextMessage(WebSocketSession session, TextMessage message) {
            // ...
        }
    
        @Override
        public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
            log.info("Info: WebSocket connection closed.");
        }
    
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
    
        }
    
    }
    

    3.WebSocketConfigurer

    配置WebSocketHandler 映射到特定的URL,设置允许跨域,设置消息缓冲区大小,设置空闲连接超时时长

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.TaskScheduler;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
    
    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Autowired
        private MyHandler myHandler;
    
        /**
         * sockJs 低版本浏览器不支持webSocket时使用
         * url结构:http://host:port/{endpoint}/{server-id}/{session-id}/websocket
         * 也可以: ws://host:port/{endpoint}/websocket
         * <p>
         * 不使用sockJs 访问时 url: ws://host:port/{endpoint}
         * <p>
         * setClientLibraryUrl 兼容客户端sockJs版本
         */
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
     
            registry.addHandler(myHandler, "/myHandler").setAllowedOrigins("*");
            registry.addHandler(myHandler, "/myHandler").setAllowedOrigins("*").withSockJS()
                    .setTaskScheduler(sockJsScheduler()).setClientLibraryUrl("//cdn.jsdelivr.net/sockjs/1/sockjs.min.js");
        }
    
        @Bean
        public ServletServerContainerFactoryBean createWebSocketContainer() {
            ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
            // ws 传输数据的时候,数据过大有时候会接收不到,所以在此处设置bufferSize
            container.setMaxTextMessageBufferSize(512000);
            container.setMaxBinaryMessageBufferSize(512000);
            container.setMaxSessionIdleTimeout(15 * 60000L);
            return container;
        }
    
    }
    

    4.WebSocket Handshake

    通过集成HandshakeInterceptor,重写"before" 和 "after"的握手方法可以自定义HTTP和WebSocket的握手请求。例如,有一个内置的拦截器通过HTTP会话属性封装到WebSocket会话属性:

    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(new MyHandler(), "/myHandler")
                .addInterceptors(new HttpSessionHandshakeInterceptor());
        }
    
    }
    
    @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
    
            HttpSession session = getSession(request);
            if (session != null) {
                if (isCopyHttpSessionId()) {
                    attributes.put(HTTP_SESSION_ID_ATTR_NAME, session.getId());
                }
                Enumeration<String> names = session.getAttributeNames();
                while (names.hasMoreElements()) {
                    String name = names.nextElement();
                    if (isCopyAllAttributes() || getAttributeNames().contains(name)) {
                        attributes.put(name, session.getAttribute(name));
                    }
                }
            }
            return true;
        }
    

    5.Server config

    每一个websocket 引擎都会暴露一些配置属性用于控制运行时的特性,比如说消息缓冲区的大小,空闲超时时长等等。
    对于Tomcat来说,可以添加ServletServerContainerFactoryBean 到你的Websocket Java Config 来控制

    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Bean
        public ServletServerContainerFactoryBean createWebSocketContainer() {
            ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
            container.setMaxTextMessageBufferSize(8192);
            container.setMaxBinaryMessageBufferSize(8192);
            container.setMaxSessionIdleTimeout(15 * 60000L);
            return container;
        }
    
    }
    

    相关文章

      网友评论

        本文标题:SpringBoot 集成 WebSocket

        本文链接:https://www.haomeiwen.com/subject/ygofjqtx.html