您现在的位置是:首页 >技术杂谈 >浅测SpringBoot环境中使用WebSocket(多端实时通信)网站首页技术杂谈

浅测SpringBoot环境中使用WebSocket(多端实时通信)

Mao.O 2023-06-06 00:00:02
简介浅测SpringBoot环境中使用WebSocket(多端实时通信)

目录

概述

测试:前端代码

后端代码(SpringBoot环境)

 1.创建处理器类(用于处理连接和消息)

2.创建配置类(用于注册处理器类,开启WebSocket)

连接测试


概述

 这篇博客主要是记录测试使用WebSocket的过程。

需求说明:最近在做一个预约系统,有用户端和医生端,用户端展示着自己的预约信息和其他用户的预约信息,医生端展示着所有人的预约信息和操作按钮,医生端是可以进行预约的处理,例如"接诊","完成"和"错过时间"等处理操作,当医生进行这类操作以后,需要通知到所有用户端进行数据更新,以展示最新的预约状态。

总结:医生端操作,服务器广播消息给所有连接的用户端,用户端接收到消息进行数据的重新获取,进行数据实时更新。

需求分析:根据需求,我们只要做到医生端建立连接并向服务器发送指定内容,服务器接收到指定内容后,向所有已连接上的客户端发送更新指令(广播),客户端接收到后进行数据的重新获取展示,就能达到根据医生操作数据实时更新数据的效果。

实现

1.定时轮询:为了达到如上需求,我们可以进行定时轮询,也就是定时向服务器获取最新的数据,这是种简单的实现思路,但是耗性能并且实时更新的效率也不高。

2.WebSocket:使用WebSocket的话就好了许多,只需要用户端向服务器进行一次连接,那么就能进行多次通信,并且通信可以是双向的。如下使用此方式实现演示。

测试:前端代码

前端代码创建WebSocket对象,连接并发送消息。

简单测试界面:

 前端代码(原生JS实现)

<div id="container">
	<h2>WebSocketTest</h2><br>
	内容<input type="text" id="myInput"><br><br>
	<button id="linkServer">连接并发送消息</button>
</div>

<script>
	// 获取输入框内容-发送的消息
	let myInput =  document.querySelector("#myInput")
	// 发送按钮,触发连接并发送消息。
	document.querySelector("#linkServer").onclick = function(){
		// 触发下方方法
		connect(myInput.value);
	}
	
	// 创建WebSocket对象并发送消息,接收消息。
	function connect(sendMsg){
		// 创建WebSocket对象
        // ws://localhost:8787/myWebSocket为后端开放的访问路径
		const socket = new WebSocket('ws://localhost:8787/myWebSocket');
		// 监听连接打开事件
		socket.onopen = function(event) {
		  console.log('WebSocket连接已打开');
		  
		  // 发送消息
		  socket.send(sendMsg);
		  console.log("客户端发送的消息是:",sendMsg);
		};
		
		// 监听接收消息事件
		socket.onmessage = function(event) {
		  console.log('接收到消息:', event.data);
		};
		
		// 监听连接关闭事件
		socket.onclose = function(event) {
		  console.log('WebSocket连接已关闭');
		};
		
		// 监听连接错误事件
		socket.onerror = function(event) {
		  console.error('WebSocket连接发生错误');
		};
	}
</script>

后端代码(SpringBoot环境)

导入依赖(pom.xml)

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

 1.创建处理器类(用于处理连接和消息)

package com.mh.common;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Date:2023/4/20
 * author:zmh
 * description: WebSocket消息处理类
 **/

@Component
public class MyWebSocketHandler implements WebSocketHandler {

    // 维护所有连接会话的列表
    private List<WebSocketSession> sessions = new ArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 将新连接的Session加入到集合中
        this.sessions.add(session);
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        // 获取前端传入的消息
        String payload = (String) message.getPayload();
        // 根据传入消息不同,响应不同消息
        if ("student".equals(payload)){
            session.sendMessage(new TextMessage("student,hi!"));
        } else if ("doctor".equals(payload)) {
            session.sendMessage(new TextMessage("doctor,hi!"));
        } else if ("maohe101".equals(payload)) {
            // 广播前将此临时通知连接删除,因为我们每次发送广播通知前端都会新创建一个连接。
            session.close();
            // 将消息广播到所有已连接的会话上
            for (WebSocketSession s : this.sessions) {
                s.sendMessage(new TextMessage("预约信息已变更,请重载数据!"));
            }

        }else {
            session.sendMessage(new TextMessage("你好!"));
        }

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // 处理错误的连接,将连接删除
        this.sessions.remove(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        // 处理主动关闭的连接
        this.sessions.remove(session);
    }

    @Override
    public boolean supportsPartialMessages() {
        // 关闭部分消息的处理,等待所有消息到达后在做处理
        return false;
    }
}

2.创建配置类(用于注册处理器类,开启WebSocket)

package com.mh.config;

import com.mh.common.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 * Date:2023/4/20
 * author:zmh
 * description: WebSocket配置类
 **/

@Configuration 
@EnableWebSocket // 开启WebSocket
public class MyWebSocketConfig implements WebSocketConfigurer {
    
    // 注入自定义的处理器类
    @Autowired
    private MyWebSocketHandler myWebSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 注册自定义处理器类,指定访问入口,并指定所有源均可连接WebSocket
        registry.addHandler(myWebSocketHandler,"/myWebSocket").setAllowedOrigins("*");
    }
}

连接测试

 根据后端代码,当服务器接收到前端发送的消息:"maohe101"之后,就会广播指定消息:”预约信息已变更,请重载数据!“,那么客户端接收到此广播的消息,就进行数据的重新拉取,实现数据的实时更新。这也就解决了我们的需求,当医生端操作后,就向服务器发送"maohe101"那么就能实现通知所有客户端更新数据的需求了。

模拟客户端连接

模拟医生端连接

医生端发送更新指令(触发广播消息)

----------------

===> 至此,测试完毕。<===

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。