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日

相关文章

  • 对Vue3中reactive的深入理解

    当我们在Vue3中使用reactive函数时,需要了解以下几个概念: reactive函数用于将数据转换为响应式数据对象,返回一个Proxy代理对象,该对象会拦截对其属性的所有读取和修改操作,从而实现响应式更新 ref函数用于将基础类型数据转换为响应式数据对象,返回一个Ref对象。Ref对象和Proxy对象一样也可以在模板或者JS代码中使用,并且也会自动追踪…

    Vue 2023年5月28日
    00
  • 利用百度echarts实现图表功能简单入门示例【附源码下载】

    以下是利用百度echarts实现图表功能简单入门示例的完整攻略: 什么是百度echarts 百度echarts是一个基于HTML5 Canvas的可视化图表库,由百度开发并开源。它支持多种常用的图表类型,如折线图、柱状图、饼图等,而且提供了丰富的配置和交互方式,能够满足大部分图表需求。 步骤 1. 引入echarts库 在需要使用echarts的页面中,首先…

    Vue 2023年5月28日
    00
  • 浅谈vue3中effect与computed的亲密关系

    浅谈vue3中effect与computed的亲密关系 什么是effect和computed 在vue3中,effect和computed是两种常用的API。effect是用来观察响应式状态的变化,而computed是用来派生一个新的响应式状态,根据已有的响应式状态计算出新的响应式状态的值。 effect 下面是一个简单的示例,演示了如何通过effect去观…

    Vue 2023年5月28日
    00
  • Vue中render函数的使用方法

    下面是对于Vue中render函数的使用方法的完整攻略。 什么是render函数? render函数是Vue中用于生成元素的函数,我们可以在这里对元素进行逻辑处理和渲染。在渲染过程中,我们可以利用一个包含h函数的上下文对象来生成元素,h函数会返回一个虚拟节点。 render函数的语法 render (h) { return h(‘div’, { attrs:…

    Vue 2023年5月28日
    00
  • vue改变对象或数组时的刷新机制的方法总结

    针对“vue改变对象或数组时的刷新机制的方法总结”这个话题,我可以给出以下攻略: 概述 在Vue中,对于对象或数组的变化,页面并不会自动刷新。为了让页面正确地呈现最新的数据,我们需要手动触发Vue的响应式机制,并让页面重新渲染。本文将总结几种改变对象或数组时的刷新机制方法。 方法总结 直接使用Vue.set() 如果我们在局部对象中添加属性,或者在数组中添加…

    Vue 2023年5月28日
    00
  • vue keep-alive的简单总结

    下面我来为你详细讲解 “Vue Keep-alive 的简单总结”攻略。 什么是 Vue Keep-alive? Vue Keep-alive是 Vue 组件中的一个内置组件。它的作用是用来缓存组件,能够保留它们的状态或避免重新渲染。通俗来说,就是把需要缓存的组件分别缓存起来,当需要重新渲染这些组件时,从缓存里面调用,而不是重新渲染一个新的组件。 Vue K…

    Vue 2023年5月27日
    00
  • 一次用vue3简单封装table组件的实战过程

    下面给出使用Vue 3简单封装table组件的完整攻略: 1. 创建组件 首先,我们需要在Vue项目中创建一个table组件。可以通过以下命令创建: vue create my-app 其中,my-app是你的项目名称。 在创建好项目后,我们可以在src/components目录下创建一个table目录,并在其中添加Table.vue文件来实现Table组件…

    Vue 2023年5月28日
    00
  • vue 内置过滤器的使用总结(附加自定义过滤器)

    下面是详细讲解“vue 内置过滤器的使用总结(附加自定义过滤器)”的完整攻略,过程中将给出两个示例来说明。 1. vue 内置过滤器 Vue 提供了一些内置的过滤器,用于快速展示数据的不同格式。这些过滤器可以在插值表达式和 v-bind 指令中使用。 1.1 文本格式化 {{message | capitalize}}: 将信息的第一个字母大写。 {{mes…

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