springBoot项目+websocket+vue实现双向通信

目录

一、了解 WebSocket 协议

WebSocket特点

      实时通信:

       双向通信:

       长连接:

        跨域通信:

二、后端代码实现

引入maven依赖

WebSocketConfig

WebSocketConfig作用:

WebSocketConfig.java代码

MyWebSocket

@注解解释

MyWebSocket作用:

MyWebSocket.java代码

三测试服务端是否正常连接

1、打开websocket测试小工具

2、在测试小工具中输入访问地址,点击连接,如下图

​编辑

四、前端代码实现

五、效果展示​编辑


一、了解 WebSocket 协议

        WebSocket 是一种全双工、长连接的通信协议,旨在提供实时通信能力。在使用 WebSocket 之前,建议先学习 WebSocket 协议的基本知识。

WebSocket特点

      实时通信:

        WebSocket 提供了一种在客户端和服务器之间进行实时通信的机制。与传统的 HTTP 请求-响应模式不同,WebSocket 允许服务器主动向客户端推送消息,而不需要客户端发起请求。这使得实时聊天、实时数据更新等实时应用成为可能。

       双向通信:

        WebSocket 可以实现双向通信,客户端和服务器可以同时发送和接收消息。无论是在客户端还是在服务器端,都可以通过发送消息来进行实时更新、通知和响应。这使得开发者可以更方便地构建交互性强、响应快速的应用程序。

       长连接:

        传统的 HTTP 请求-响应模式使用短连接,即每次请求都需要建立新的连接和关闭连接。相比之下,WebSocket 使用长连接,即一次连接可以持续有效并传输多个消息。这减少了连接建立和关闭的开销,并减少了网络流量和延迟,从而提高了应用的效率和性能。

        跨域通信:

        WebSocket 协议支持跨域通信,也就是在不同域名或不同端口之间进行通信。这使得开发者可以构建分布式系统,将不同模块或服务放置在不同的主机上,并通过 WebSocket 进行实时通信和数据交换。

二、后端代码实现

引入maven依赖

<!--  socket启动依赖         -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.7.0</version>
</dependency>

WebSocketConfig

WebSocketConfig作用:

        开启 WebSocket 的支持,并将该类注入到 Spring 容器中。具体来说,它通过在 Spring 配置文件中注册一个 ServerEndpointExporter Bean,用于扫描所有带有 @ServerEndpoint 注解的 WebSocket 服务,并将其注册到 WebSocket 容器中。这样就可以在 Spring Boot 应用程序中使用 WebSocket 实现实时通信和数据传输了。    

WebSocketConfig.java代码

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket的支持,并把该类注入到spring容器中
 * @description: WebSocket配置
 * @author: 戈壁老孙
 * @create: 2023/11/08 10:28
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

MyWebSocket

@注解解释

@ServerEndpoint("/websocket") 注解表示将该类标识为一个 WebSocket 服务端端点,客户端可以通过该端点进行 WebSocket 连接。/websocket 是客户端连接的 URL 路径。

@EnableScheduling 注解表示启用 Spring 的定时任务调度功能。在该类中使用的 @Scheduled 注解才能生效。

@Component 注解表示将该类标识为一个 Spring 组件,由 Spring 自动进行管理和注入。

综合起来,使用这些注解标注的类为一个 WebSocket 服务端的实现类,同时支持定时任务调度,并由 Spring 自动进行管理和注入。客户端可以通过访问 /websocket 路径来与该 WebSocket 服务端建立连接。

MyWebSocket作用:

         使用了 @ServerEndpoint 注解声明 websocket 服务端的地址。在收到客户端发来的消息时,会进入 onMessage 方法,进行消息的处理。同时,在客户端进行连接或关闭连接的时候,则会进入对应的 onOpen 和 onClose 方法。此外,使用了一个静态变量 onlineCount 表示当前连接的 WebSocket 数量,并使用 CopyOnWriteArraySet 类型的 webSocketSet 保存所有连接的 WebSocket 实例。在加入连接时,调用 addOnlineCount() 增加在线人数记录,退出连接时,调用 subOnlineCount() 减少在线人数记录。最后,使用了 @Autowired 注解注入IProTriaxialDataService 的 bean,用于处理业务逻辑。

MyWebSocket.java代码


import com.alibaba.fastjson2.JSONObject;
import com.unis.common.utils.StringUtils;
import com.unis.web.domain.ProTriaxialData;
import com.unis.web.service.IProTriaxialDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * socket 通信类
 * @description: WebSocket配置
 * @author: 戈壁老孙
 * @create: 2023/11/08 10:30
 */
@ServerEndpoint("/websocket")
@EnableScheduling
@Component
public class MyWebSocket {

    private static final Logger log = LoggerFactory.getLogger(MyWebSocket.class);


    private static int onlineCount = 0;

    private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<>();

    private Session session;

    private Boolean isReceive = true;

    //业务注入
    private static IProTriaxialDataService proTriaxialDataService;

    @Autowired
    public void proTriaxialDataService(IProTriaxialDataService proTriaxialDataService){
        //WebScoketController是该类的类名 需要换成自己的类名
        MyWebSocket.proTriaxialDataService = proTriaxialDataService;
    }


    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);
        addOnlineCount();
        log.info("有新链接加入!当前在线人数:{}",getOnlineCount());
    }

    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        subOnlineCount();
        log.info("有一链接关闭!当前在线人数:{}",getOnlineCount());
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        log.info("socket 接收到信息{}",message);
        //判断前端是否已消费上一条信息
        if (StringUtils.isNotEmpty(message) && message.equals("已消费")){
            isReceive = true;
        } else {
            // 连接已断开
            isReceive = false;
        }
    }

    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    @Scheduled(cron = "*/5 * * * * *")
    public void sendMessageScheduledTask()throws Exception{
        log.info("socket 执行三数据推送给前端");
        try{
            if (isReceive){
                //每五秒发送一次
                List<ProTriaxialData> proTriaxialData = proTriaxialDataService.selectProTriaxialDataByCreateTimeDesc();
                if (proTriaxialData!=null && proTriaxialData.size()>0){
                    String message = JSONObject.toJSONString(proTriaxialData.get(0));
                    for (MyWebSocket item : webSocketSet) {
                        item.sendMessage(message);

                    }
                }
            }
            log.info("socket 数据发送成功!");
        }catch (Exception e){
            log.info("socket 数据发送失败!");
            e.printStackTrace();
        }

    }


    public static synchronized int getOnlineCount() {
        return MyWebSocket.onlineCount;
    }

    public static synchronized void addOnlineCount() {
        MyWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        MyWebSocket.onlineCount--;
    }

}

三测试服务端是否正常连接

1、打开websocket测试小工具

        

2、在测试小工具中输入访问地址,点击连接,如下图

        ws://IP:PORT/websocket 

四、前端代码实现

created() {
      var ws = new WebSocket("ws://IP:PORT/websocket");

      // 连接成功后的回调函数
      ws.onopen = function (params) {
        console.log('客户端连接成功')
        // 向服务器发送消息
        ws.send('认证成功!')
      };
      // 从服务器接受到信息时的回调函数
      ws.onmessage = function (e) {
        console.log('收到服务器响应', e.data)
        this.proTriaxialData = e.data;
        console.log( this.proTriaxialData);
      };
      // 连接关闭后的回调函数
      ws.onclose = function(evt) {
        console.log("关闭客户端连接");
      };
      // 连接失败后的回调函数
      ws.onerror = function (evt) {
        console.log("连接失败了");
      };
      // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,这样服务端会抛异常。
      window.onbeforeunload = function() {
        ws.close();
      }

      console.log(ws)
    }

五、效果展示

到这里就结束啦~

猜你喜欢

转载自blog.csdn.net/weixin_44719880/article/details/134295842