• websocket学习笔记【springboot+websocket聊天室demo】


    WebSocket是什么?

    WebSocket是一种基于TCP协议的双向通信协议,它允许服务器和客户端之间建立持久的连接。与传统的HTTP请求/响应模型不同,WebSocket连接一旦建立,可以在不断开的情况下双向传输数据。这使得WebSocket在实时应用中非常有用,例如在线游戏、即时聊天、实时协作工具等。

    为什么需要WebSocket?

    尽管HTTP协议广泛应用于网络通信,但它存在一个关键的局限性:通信只能由客户端发起。这种方式在需要频繁的数据更新和实时交互的场景中效率低下。例如,在一个聊天应用中,使用HTTP协议,客户端需要不断地发送请求以检查新消息,这种“轮询”机制浪费了大量的资源。WebSocket应运而生,解决了这个问题,通过建立一个持久的连接,实现了更高效的数据交换。

    WebSocket和Http连接的区别

    • 通信方式:
      HTTP: HTTP是一种无状态协议,每次请求都是独立的,即使是在同一个客户端和服务器之间的多次请求。客户端向服务器发送请求,服务器处理请求并返回响应,然后连接关闭。HTTP通常是一种请求/响应协议。
      WebSocket: WebSocket是一种全双工协议,允许双方建立持久性的连接,以便在连接建立后双向传输数据。WebSocket支持实时通信,允许服务器和客户端随时发送数据,而无需为每个消息建立新的连接。

    • 连接建立:
      HTTP: HTTP连接是临时的,每个请求都需要建立新的TCP连接,完成后即刻关闭。这导致了额外的延迟,尤其是在需要频繁通信的实时应用中。
      在这里插入图片描述

      WebSocket: WebSocket连接是持久的,一旦建立,它可以一直保持开放状态,不需要在每次通信之间重新建立连接。这减少了延迟,并使它适用于实时应用。
      在这里插入图片描述

    • 头部信息:
      HTTP: HTTP请求和响应通常包括大量的头部信息,用于描述请求的属性、内容类型等。这些头部信息会占用额外的带宽,尤其是在小数据传输中显得不必要。
      WebSocket: WebSocket头部信息相对较少,因为它专注于数据传输,减少了不必要的开销。

    • 用途:
      HTTP: HTTP主要用于请求和获取资源,如网页、图像、文档等。每个HTTP请求都是短暂的,没有保持连接的需求。
      WebSocket: WebSocket适用于需要实时通信、双向数据交换的应用,如在线游戏、实时聊天、实时协作工具、监控系统等。

    • 安全性:
      HTTP: HTTP本身不提供加密,因此数据可以被拦截和窥探。但HTTPS通过TLS/SSL协议提供了数据加密和安全性。
      WebSocket: WebSocket也可以通过WSS(WebSocket Secure)协议提供加密和安全性,以确保数据的机密性。

    WebSocket的工作原理

    基本交互过程:

    1. 握手阶段: 客户端通过发送HTTP升级请求到服务器来启动WebSocket连接。服务器收到这个请求后,如果支持WebSocket,它将回复一个HTTP 101切换协议的响应,从而建立WebSocket连接。

    2. 数据传输: 一旦WebSocket连接建立,客户端和服务器可以双向传输数据。无论是客户端还是服务器,都可以随时向对方发送消息。这种双向通信的实时性使WebSocket在很多应用场景中非常有用。

    3. 关闭连接: 当需要关闭WebSocket连接时,任一方可以发送一个关闭帧,通知对方关闭连接。这确保了连接的正常关闭,释放资源。

    Java中的WebSocket支持

    Java提供了多种库和框架来支持WebSocket技术,其中最知名的是Java API for WebSocket(JSR-356),它是Java EE 7规范的一部分。Java WebSocket API允许你在Java应用程序中创建WebSocket服务器和客户端。

    WebSocket的优势

    减少开销: 在建立连接后,WebSocket不需要像HTTP那样为每个消息发送额外的头信息,这降低了通信的总体开销。
    实时性: 全双工通信使得消息可以即时发送和接收,非常适合需要实时数据交互的应用。
    节省资源: 相比于HTTP轮询,WebSocket通过维持持久连接减少了频繁建立和断开连接的资源消耗。

    springboot + websocket + themlef 一个聊天室demo

    在这里插入图片描述

    pom.xml

    		<dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-websocketartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-thymeleafartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    WebSocketConfig

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/chat").withSockJS();
        }
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            registry.enableSimpleBroker("/topic");
            registry.setApplicationDestinationPrefixes("/app");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ChatController

    @Controller
    public class ChatController {
    
        @MessageMapping("/sendMessage")
        @SendTo("/topic/public")
        public String sendMessage(String message) {
            return message;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    WebController

    @Controller
    public class WebController {
        @GetMapping("/chat")
        public String chat() {
            return "chat"; // Thymeleaf 模板文件的名称(不包含 .html 扩展名)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    chat.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Chat Room</title>
        <script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/stomp-websocket/lib/stomp.min.js"></script>
        <style>
            #messageArea {
                height: 300px;
                overflow-y: auto;
                border: 1px solid #cccccc;
                padding: 10px;
                margin-bottom: 10px;
            }
    
            .chat-message {
                margin-bottom: 10px;
                border: 1px solid #dddddd;
                padding: 5px;
                border-radius: 5px;
            }
        </style>
    </head>
    <body>
    <div id="chatPage">
        <div id="messageArea"></div>
        <input type="text" id="messageInput" placeholder="Type a message...">
        <button onclick="sendMessage()">Send</button>
    </div>
    <script th:inline="javascript">
        var stompClient = null;
        function connect() {
            var socket = new SockJS('/chat');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function (frame) {
                stompClient.subscribe('/topic/public', function (message) {
                    showMessage(message.body);
                });
            });
        }
    
        function sendMessage() {
            var message = document.getElementById('messageInput').value;
            stompClient.send("/app/sendMessage", {}, message);
            document.getElementById('messageInput').value = '';
        }
    
        function showMessage(message) {
            var messageArea = document.getElementById('messageArea');
            var messageElement = document.createElement('div');
            messageElement.classList.add('chat-message');
            messageElement.innerText = message;
            messageArea.appendChild(messageElement);
        }
    
        connect();
    </script>
    </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    application.yml

    server:
      port: 8081
    
    spring:
      thymeleaf:
        mode: HTML
        cache: true
        prefix: classpath:/templates/
        encoding: UTF-8
        suffix: .html
        check-template-location: true
        template-resolver-order: 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试效果

    在浏览器访问http://localhost:8081/chat,打开多个界面
    在这里插入图片描述
    在其中一个窗口发送信息
    在这里插入图片描述
    其他窗口都收到了信息
    在这里插入图片描述

  • 相关阅读:
    南京邮电大学电工电子基础B实验三(交流参数的测量)
    剑指Offer || 105.岛屿的最大面积
    CPU与GPU到底有什么区别?
    文章分类列表进行查询(实体类日期格式设置)
    2022杭电多校九 1008-Shortest Path in GCD Graph(质因子+容斥)
    071:vue+openlayers轨迹路线动画(示例代码)
    微服务学习第十一节
    基于K8s构建Jenkins持续集成平台(部署流程)(转了一点)
    互联网摸鱼日报(2023-11-20)
    Synopsys新思科技2023“向新力”秋季校园招聘内推
  • 原文地址:https://blog.csdn.net/qq_33129875/article/details/134166529