SpringBoot+WebSocket实现即时通讯的方法详解

以下是详细讲解“SpringBoot+WebSocket实现即时通讯的方法详解”的完整攻略。

一、前置知识

在学习本篇攻略之前需要了解以下知识点:

  1. SpringBoot框架的基础知识
  2. WebSocket协议的相关知识
  3. Springboot整合WebSocket的基础知识

二、SpringBoot集成WebSocket的步骤

1.创建SpringBoot项目

我们首先需要创建一个新的SpringBoot项目,可以使用Spring Initializr来帮助我们快速生成一个基础项目,推荐使用Maven或Gradle来管理项目。

2.添加WebSocket依赖

在项目的pom.xml文件中添加以下依赖:

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

3.创建WebSocket配置类

在项目的src/main/java目录下创建一个新的package,命名为com.example.websocket.config,然后在该package下创建WebSocketConfig类,代码如下所示:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyHandler(), "/myHandler")
                .addInterceptors(new HandshakeInterceptor() {
                    @Override
                    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                                   WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
                        // 处理握手前的逻辑
                        return true;
                    }

                    @Override
                    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                                WebSocketHandler wsHandler, Exception exception) {
                        // 处理握手后的逻辑
                    }
                }).setAllowedOrigins("*");
    }

    class MyHandler extends TextWebSocketHandler {

        @Override
        public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
            // 处理消息的逻辑
        }
    }
}

在上述代码中:

  • @Configuration:该注解表示将该类声明为一个配置类。
  • @EnableWebSocket:该注解表示开启WebSocket支持。
  • WebSocketConfigurer:该接口定义了WebSocket的配置信息的回调方法。
  • HandlerMapping:WebSocket的处理映射。
  • HandshakeInterceptor:WebSocket的握手拦截器。
  • MyHandler:自定义的WebSocket处理器,继承自TextWebSocketHandler。

4.编写WebSocket前端代码

Websocket协议是基于TCP的,所以我们需要使用一个WebSocket客户端来测试我们的WebSocket服务。在前端HTML页面中添加以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Example</title>
    <script>
        var socket = new WebSocket("ws://localhost:8080/echo");

        socket.onopen = function(event) {
            console.log("WebSocket opened");
            console.log(event);
        };

        socket.onmessage = function(event) {
            console.log("WebSocket received message: " + event.data);
        };

        socket.onclose = function(event) {
            console.log("WebSocket closed");
        };
    </script>
</head>
<body>
    <h1>WebSocket Example</h1>
    <p>WebSocket connection status: <span id="status">unknown</span></p>
</body>
</html>

在上述代码中,我们使用了WebSocket的JavaScript API,其中:

  • WebSocket:WebSocket的构造函数,用于创建一个WebSocket客户端实例。
  • onopen:当WebSocket连接建立时触发。
  • onmessage:当WebSocket收到消息时触发。
  • onclose:当WebSocket连接关闭时触发。

5.测试WebSocket服务

启动我们的SpringBoot项目,打开Chrome浏览器,并访问前面编写的HTML页面。在控制台中可以看到WebSocket连接成功的日志。

三、示例说明

1.代码示例一:群聊功能

我们可以使用WebSocket实现一个简单的群聊功能。

首先,我们需要在后端代码中编写一个WebSocket处理器:

class MyHandler extends TextWebSocketHandler {

    private static final List<WebSocketSession> sessions = new ArrayList<>();

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        for (WebSocketSession s : sessions) {
            if (!s.equals(session)) {
                s.sendMessage(message);
            }
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
    }
}

上述代码中:

  • sessions:保存所有已连接的WebSocketSession对象。
  • handleTextMessage:处理收到的WebSocket消息,并广播到所有已连接的WebSocketSession对象。
  • afterConnectionEstablished:当有新的WebSocket连接建立时将其添加到sessions列表中。
  • afterConnectionClosed:当有WebSocket连接关闭时,从sessions列表中将其移除。

此外,还需要在WebSocketConfig类中将MyHandler注册到WebSocket中:

registry.addHandler(new MyHandler(), "/simpleChat").setAllowedOrigins("*");

在前端代码中,我们可以使用以下JavaScript代码来触发发送消息:

<body>
    <h1>群聊</h1>
    <div>
        <textarea id="message" rows="3"></textarea>
        <button onclick="sendMessage()">发送</button>
    </div>
    <ul id="messages"></ul>

    <script>
        var socket = new WebSocket("ws://localhost:8080/simpleChat");
        var messageInput = document.getElementById("message");
        var messageList = document.getElementById("messages");

        socket.onmessage = function(event) {
            var message = event.data;
            messageList.innerHTML += "<li>" + message + "</li>";
        };

        function sendMessage() {
            var message = messageInput.value;
            socket.send(message);
            messageInput.value = "";
        }
    </script>
</body>

可以看到,我们在HTML页面中添加了一个文本框、一个发送按钮和一个消息列表。当用户点击发送按钮时,JavaScript代码调用WebSocket的send方法发送消息。同时,当WebSocket接收到消息时,JavaScript代码将消息添加到页面的消息列表中。这样就实现了一个简单的群聊应用。

2.代码示例二:在线聊天室

我们可以使用WebSocket实现一个在线聊天室。

首先,我们需要在后端代码中编写一个WebSocket处理器:

class ChatHandler extends TextWebSocketHandler {

    private static final Map<String, WebSocketSession> connections = new ConcurrentHashMap<>();

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        String payload = message.getPayload();
        ObjectMapper objectMapper = new ObjectMapper();
        ChatMessage chatMessage = objectMapper.readValue(payload, ChatMessage.class);
        String recipient = chatMessage.getRecipient();
        if (recipient == null) {
            broadcastMessage(chatMessage);
        } else {
            sendMessageToUser(recipient, chatMessage);
        }
    }

    private void broadcastMessage(ChatMessage chatMessage) throws IOException {
        String payload = chatMessage.toJsonString();
        TextMessage message = new TextMessage(payload);
        for (WebSocketSession session : connections.values()) {
            session.sendMessage(message);
        }
    }

    private void sendMessageToUser(String userId, ChatMessage chatMessage) throws IOException {
        String payload = chatMessage.toJsonString();
        TextMessage message = new TextMessage(payload);
        WebSocketSession session = connections.get(userId);
        if (session != null && session.isOpen()) {
            session.sendMessage(message);
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userId = session.getUri().getQuery().split("=")[1];
        connections.put(userId, session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        for (Map.Entry<String, WebSocketSession> entry : connections.entrySet()) {
            if (entry.getValue().equals(session)) {
                connections.remove(entry.getKey());
            }
        }
    }
}

上述代码中:

  • connections:保存所有已连接的WebSocketSession对象。
  • handleTextMessage:处理收到的WebSocket消息,并根据消息中的recipient字段决定是广播消息还是向某个用户发送消息。
  • broadcastMessage:广播消息到所有已连接的WebSocketSession对象。
  • sendMessageToUser:向指定用户发送消息。
  • afterConnectionEstablished:当有新的WebSocket连接建立时从连接URI中获取用户ID,将其添加到connections中。
  • afterConnectionClosed:当有WebSocket连接关闭时,从connections中将其移除。

此外,还需要在WebSocketConfig类中将ChatHandler注册到WebSocket中:

registry.addHandler(new ChatHandler(), "/chat").setAllowedOrigins("*");

在前端代码中,我们可以使用以下JavaScript代码来触发发送消息:

<body>
    <h1>在线聊天室</h1>

    <label for="userId">用户名:</label>
    <input type="text" id="userId"/>
    <button onclick="connect()">登录</button>

    <div style="display: none" id="chat">
        <hr/>
        <div>
            <ul id="messages"></ul>
            <br/>
            <div>
                <label for="recipient">私聊对象:</label>
                <input type="text" id="recipient"/>
            </div>
            <br/>
            <div>
                <textarea id="message" rows="3"></textarea>
                <button onclick="sendMessage()">发送</button>
            </div>
        </div>
    </div>

    <script>
        var userIdInput = document.getElementById("userId");
        var chatDiv = document.getElementById("chat");
        var messagesList = document.getElementById("messages");
        var recipientInput = document.getElementById("recipient");
        var messageInput = document.getElementById("message");
        var chatSocket = null;

        function connect() {
            var userId = userIdInput.value;
            if (userId.trim() !== "") {
                chatDiv.style.display = "block";
                var host = window.location.hostname;
                chatSocket = new WebSocket("ws://" + host + ":8080/chat?userId=" + userId);
                chatSocket.onmessage = function(event) {
                    var payload = event.data;
                    var chatMessage = JSON.parse(payload);
                    var sender = chatMessage.sender;
                    var message = chatMessage.message;
                    var item = "<li>";
                    if (sender !== "") {
                        item += sender + ": ";
                    }
                    item += message + "</li>";
                    messagesList.innerHTML += item;
                };
            }
        }

        function disconnect() {
            chatSocket.close();
            chatDiv.style.display = "none";
        }

        function sendMessage() {
            var message = messageInput.value;
            var recipient = recipientInput.value;
            var payload = JSON.stringify({recipient: recipient, message: message});
            chatSocket.send(payload);
            messageInput.value = "";
        }
    </script>
</body>

可以看到,我们在HTML页面中添加了用户名输入框、登录按钮、聊天界面和在线用户列表。当用户在登录框中输入名字并点击登录按钮时,JavaScript代码会通过WebSocket连接到后端并发送用户ID。发起连接后,聊天界面会显示出来。用户可以在输入框中输入消息并点击发送按钮。当有新的消息到来时,JavaScript代码会将其添加到在线用户列表和消息列表中。

四、总结

本篇攻略中,我们讲解了如何使用SpringBoot和WebSocket协议实现即时通讯的方法。具体来说,我们分别讲解了SpringBoot集成WebSocket的步骤和两个示例代码。实现即时通讯功能是很有趣的,希望可以帮助读者更好地理解WebSocket和SpringBoot的使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot+WebSocket实现即时通讯的方法详解 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • vue最简单的前后端交互示例详解

    下面是“vue最简单的前后端交互示例详解”的完整攻略。 总览 前后端交互是Web开发中的重要环节,Vue作为现代化的前端框架,提供了多种方式来与后端服务交互。本文将会介绍Vue前端框架如何处理前后端交互,包括如何发送Ajax请求、获取/提交数据等。 准备工作 在开始前,我们需要先了解以下基础知识: Vue.js基础语法 前端模块化开发 发送Ajax请求 我们…

    Vue 2023年5月28日
    00
  • vsCode中vue文件无法提示html标签的操作方法

    针对vsCode中vue文件无法提示html标签的情况,可以按照以下步骤进行操作: 安装Vetur插件 Vetur是一款vsCode的插件,主要提供语法高亮、格式化、代码片段和错误提示等功能,适用于Vue.js开发。因此,在使用vsCode编辑Vue文件时,我们需要安装并启用Vetur插件,这样就能够解决无法提示html标签的问题。 具体操作如下: 在vsC…

    Vue 2023年5月28日
    00
  • vue深拷贝的3种实现方式小结

    本文将详细讲解三种vue深拷贝的实现方式,分别为递归实现、JSON.parse/stringify、lodash库实现。下面将分为以下几个部分来介绍。 1. 递归实现 递归实现是一种最简单的深拷贝方式,其代码实现如下: function deepClone(obj) { if (obj === null || typeof obj !== "obj…

    Vue 2023年5月27日
    00
  • 浅谈vue2的$refs在vue3组合式API中的替代方法

    下面是关于“浅谈vue2的$refs在vue3组合式API中的替代方法”的详细讲解攻略: 1、什么是$refs 在Vue2中,我们可以通过在模板中给DOM元素添加ref属性,然后通过this.$refs来访问这个元素或组件实例,这个访问实例的方式就是Vue2中的$refs。 2、在vue3组合式API中$refs有什么改变 在Vue3中,Vue官方推荐使用组…

    Vue 2023年5月28日
    00
  • Vue监听一个数组id是否与另一个数组id相同的方法

    要监听一个数组中对象的属性,需要用到 Vue 中提供的 $watch 或 $watchCollection 方法。具体实现步骤如下: 在数据中定义两个数组,分别为 idArray 和 targetArray,如下代码所示: data() { return { idArray: [1, 2, 3], targetArray: [{id: 1, name: ‘T…

    Vue 2023年5月29日
    00
  • Vue 解决在element中使用$notify在提示信息中换行问题

    要在 element-ui 的 $notify 中进行换行,可以使用 html 标签进行内容换行。但是,直接在 $notify 中插入 html 标签会将其解析为字符串,而不是渲染成为 html 元素。因此许多人会通过使用 dangerouslyUseHTMLString 属性,来将 <br> 等 html 标签渲染为真正的 html 元素。 以…

    Vue 2023年5月27日
    00
  • Vue混入与插件的使用介绍

    下面将对Vue混入与插件的使用进行详细讲解。 什么是Vue混入? Vue混入是一种分发Vue组件中可复用功能的非常灵活的方式。混入(mixin)对象可以包含任意组件选项。当组件使用混入对象时,混入对象中的选项会被“混入”到组件自身的选项中。换句话说,混入就是将一些组件中相同的部分提取出来,然后在多个组件中共用。 混入的应用场景很广泛,例如:多个组件都需要注入…

    Vue 2023年5月28日
    00
  • vue源码学习之Object.defineProperty对象属性监听

    下面我来详细讲解“vue源码学习之Object.defineProperty对象属性监听”的完整攻略。 标题 vue源码学习之Object.defineProperty对象属性监听 简介 在开发Vue.js过程中,我们经常会用到Object.defineProperty方法来实现数据响应式,也就是监听对象属性的变化。Vue.js源码中就使用了该方法来实现数据…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部