JavaWeb合集14-WebSocket

十四、WebSocket

WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信,浏览器和服务器只需要完成一次握手, 两者之间就可以创建持久性的连接,并进行双向数据传输。

HTTP协议和WebSocket协议对比:

  1. HTTP是短连接,WebSocket是长连接
  2. HTTP通信是单向的,基于请求响应模式,WebSocket支持双向通信
  3. HTTP和WebSocket底层都是TCP连接

应用场景:视频弹幕、网页聊天、体育实况更新、股票基金报价实时更新。

1、入门案例

实现步骤:

  1. 直接使用websocket.html页面作为WebSocket客户端

    html 复制代码
    <html>
    <body class="gray-bg">
     
    <div class="online">
    
           <input  id="text" type="text">
    
        <button onclick="send()">发送消息</button>
        <button onclick="closeWebSocket()">关闭连接</button>
    
        <div id="message"></div> 
      
    </div>
     
     
    <script th:inline="javascript">
        
        let websocket = null;
        let host = document.location.host;
        let sid=getRandomIntInclusive(0,1000000)
    
        function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; // 最小值和最大值都是包含的
    }
    
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            //连接WebSocket节点
            websocket = new WebSocket("ws://localhost:9091/ws/"+sid);
        } else {
            alert('浏览器不支持webSocket');
        }
        
        //连接发生错误的回调方法
        websocket.onerror = function () {
            setMessageInnerHTML("连接失败");
        };
        
        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            setMessageInnerHTML("连接成功");
        };
        
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            let data = event.data;
            console.log("后端传递的数据:" + data);
            //将后端传递的数据渲染至页面
             setMessageInnerHTML(data)
        };
        
        //连接关闭的回调方法
        websocket.onclose = function () {
            setMessageInnerHTML("已关闭");
        };
        
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            websocket.close();
        };
        
        //将消息显示在网页上
        function setMessageInnerHTML(innerHTML) {
            document.getElementById('message').innerHTML+=innerHTML+'<br/>'
        };
        
        //手动关闭连接
        function closeWebSocket() {
            websocket.close();
        };
        
        //发送消息
        function send() {
            let message = document.getElementById('text').value;
            websocket.send(message);
            setMessageInnerHTML("已向服务器发送内容:"+message+)
        };
        
    </script>
     
    </body>
    </html>
  2. 导入WebSocket的maven坐标

    xml 复制代码
    <!-- SpringBoot Websocket -->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
  3. 导入WebSocket服务端组件WebSocketServer, 用于和客户端通信

    java 复制代码
    //主要是将目前的类定义成一个websocket服务器端(就像Controller层), 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
    @ServerEndpoint("/ws/{sid}")
    @Component
    @Slf4j
    public class WebSocketService {
    
        /**
         * 用来存放所有的webSocket连接
         */
        private static Map<String,Session> sessionMap=new HashMap<>();
    
    
        /**
         * 连接建立成功调用的方法
         *
         * @param session 会话
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("sid")String sid)  {
            System.out.println("客户端:"+sid+" 连接成功!");
            sessionMap.put(sid,session); // 将当前连接加入到连接池中
        }
    
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         */
        @OnMessage
        public void onMessage(String message, @PathParam("sid") String sid) {
            System.out.println("收到来自窗口:" + sid + "的信息:" + message);
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose(@PathParam("sid") String sid) {
            log.info("窗口:" + sid + "关闭了连接");
            sessionMap.remove(sid);  // 移除连接池中的连接
        }
    
    
        /**
         * 自定义消息推送、可群发
         *
         * @param message 消息
         */
        public static void sendAllClient(String message)  {
            System.out.println("推送消息到窗口,推送内容:" + message);
            // 遍历所有连接(获取到Map的全部vaue值,进行遍历)
            for (Session item : sessionMap.values()) {
                try {
                    item.getBasicRemote().sendText(message);  // 发送消息
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
  4. 导入配置类WebSocketConfiguration, 注册WebSocket的服务端组件

    java 复制代码
    @Configuration
    public class WebSocketConfig {
        /**
         * 这个bean的注册,用于扫描带有@ServerEndpoint的注解成为websocket  ,如果你使用外置的tomcat就不需要该配置文件
         */
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }
  5. 导入定时任务类WebSocketTask, 定时向客户端推送数据

    java 复制代码
    @Component
    public class WebSocketTask {
        //将WebSocketService注入到WebSocketTask中
        @Autowired
        private WebSocketService webSocketService;
        /**
         * 每5秒执行一次
         */
        @Scheduled(cron = "0/5 * * * * ? ")
        public void webSocketService(){
            webSocketService.sendAllInfo("服务器定时推送消息: "+LocalDateTime.now());
        }
    }
相关推荐
云计算-Security8 分钟前
分组交换的可靠性来自哪里?
网络·智能路由器
ward RINL21 分钟前
# GPT-5.6-sol vs GPT-5.5 新题实测:非弹性碰撞物理题和稳定路由算法
网络·gpt·算法
wang_shu_mo_ran1 小时前
网络编程(二):UDP数据报在客户端与服务端之间的传输
网络·网络协议·udp
humors2211 小时前
【转帖】关于防范AI编程工具Claude Code安全后门隐患的风险提示
网络·安全·ai编程
深度智能科技1 小时前
IPv6无网络访问权限怎么解决?【图文讲解】Win10/Win11 IPv6无网络访问权限完整修复实操教程
网络·ipv6·深度c盘清理·ipv6协议开启自动获取ip·ipv6无网络访问权限·上不了网怎么办·防火墙拦截ipv6
梦帮科技2 小时前
Rust+Tauri+EVM:构建下一代内存安全级数字版权(DRM)主权音频网络与跨链金融系统的技术实践与全景架构
网络·安全·架构·rust·区块链·音视频·web3.py
mudtools2 小时前
HttpUtils:一个编译时生成的声明式 HTTP 客户端框架
网络·网络协议·http·.net
luj_17689 小时前
残熵算法实时化三大瓶颈突破
c语言·开发语言·网络·经验分享·算法
吴懿不在10 小时前
某次热身赛re方向wp WORDS 51,500 READ 172 MIN base64,
网络
小林ixn13 小时前
从“玩具工具”到“跨语言利器”:MCP 协议实战解析
运维·服务器·网络