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());
        }
    }
相关推荐
稳重的大王1 分钟前
为什么QNAP威联通NAS的APP center无法安装APP?
网络
我只会Traceroute10 分钟前
【渗透测试】01-信息收集-名词概念
网络·web安全·网络安全·渗透测试
爱就是恒久忍耐17 分钟前
CANopen中错误帧的制造和观测
网络·python·制造
桃酥40339 分钟前
day04|计算机网络重难点之HTTP/1.0和HTTP/1.1的区别、HTTP/2.0与HTTP/1.1的区别、介绍HTTP/3.0
网络协议·计算机网络·http
姓刘的哦44 分钟前
Boost网络库API学习笔记
网络
葱白有滋味1 小时前
浏览器无法访问非80端口网页
运维·服务器·网络
如果'\'真能转义说1 小时前
从网络到缓存:在Android中高效管理图片加载
android·网络·缓存
长安初雪2 小时前
浅析HTTP协议
网络·网络协议·http
懒惰树人2 小时前
渗透测试-百日筑基—SQL注入篇&时间注入&绕过&HTTP数据编码&绕过—下
网络·sql·安全·web安全·http·oracle
白总Server2 小时前
物联网网关确保设备安全
服务器·网络·物联网·安全·web安全·自然语言处理·架构