SpringBoot+Vue整合WebSocket实现实时通讯

这篇具有很好参考价值的文章主要介绍了SpringBoot+Vue整合WebSocket实现实时通讯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        在开发过程中,我们经常遇到需要对前台的列表数据,实现实时展示最新的几条数据,或者是调度的任务进度条实现实时的刷新......,而对于这种需求,无状态的http协议显然无法满足我们的需求,于是websocket协议应运而生。websocket协议本质上是一个基于tcp的协议,是双向通讯协议,实现了浏览器和客户端的实时通讯,接收端和发送端可以互相发送或接收消息。

        本文整合websocket方式采用后台自定义Endpoint,前端使用内置的WebSocket。

一、SpringBoot配置

1、开发环境

SpringBoot:2.5.13
JDK:1.8

2、引入pom文件

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

3、新建WebSocketConfig配置类

        在配置类中手动注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket端点。@ServerEndpoint注解与@Controller注解类似,都是用来配置请求的uri。

@Configuration
public class WebSocketConfig {

    /**
     * ServerEndpointExporter类的作用是,会扫描所有的服务器端点,
     * 把带有@ServerEndpoint 注解的所有类都添加进来
     * 
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }

}

4、新建WebSocketServer服务类

        server类用来对与前端建立的websocket连接做出相应的响应,同时通过该类我们可以主动向前台推送消息。在该类中我们无法使用通过@Resource和@Autowired注入spring容器中的bean,由于spring容器管理的bean都是以单例的形式存在的,而websocket服务类则可以对应多个客户端。 项目初始化启动时,会初始化websocket服务类,此时还没有用户连接,spring会为其注入service, 所以该对象的service不是null,而当新用户建立websocket连接时,系统会新建一个websocket服务类对象, 但不会注入service,导致后续用户连接websocket服务类中的service都是null。

@Slf4j
@Component
@ServerEndpoint("/notice/{userId}")
public class WebSocketServer {

    /**
     * 解决无法注入bean:定义静态service对象,通过@Autowired在系统启动时为静态变量赋值
     * @Autowired 注解作用在方法上,如果方法没有参数,spring容器会在类加载完后执行一次这个方法,
     * 如果方法中有参数的话,还会从容器中自动注入这个方法的参数,然后执行一次这个方法。
     */
    public static XxService xxService;

    @Autowired
    public void setXxService(XxService xxService){
        WebSocketServer.xxService = xxService;
    }

    //存储客户端session信息
    public static Map<String, Session> clients = new ConcurrentHashMap<>();

    //存储把不同用户的客户端session信息集合
    public static Map<String, Set<String>> connection = new ConcurrentHashMap<>();

    //会话id
    private String sid = null;

    //建立连接的用户id
    private String userId;

    /**
     * @description: 当与前端的websocket连接成功时,执行该方法
     * @PathParam 获取ServerEndpoint路径中的占位符信息类似 控制层的 @PathVariable注解
     **/
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId){
        this.sid = UUID.randomUUID().toString();
        this.userId = userId;
        clients.put(this.sid,session);
        //判断该用户是否存在会话信息,不存在则添加
        Set<String> clientSet = connection.get(userId);
        if (clientSet == null){
            clientSet = new HashSet<>();
            connection.put(userId,clientSet);
        }
        clientSet.add(this.sid);
        log.info(this.userId + "用户建立连接," + this.sid+"连接开启!");
    }

     /**
     * @description: 当连接失败时,执行该方法
     **/
    @OnClose
    public void onClose(){
        clients.remove(this.sid);
        log.info(this.sid+"连接断开");
    }

    /**
     * @description: 当收到前台发送的消息时,执行该方法
     **/
    @OnMessage
    public void onMessage(String message,Session session) {
        log.info("收到来自用户:" + this.userId + "的信息   " + message);
        //自定义消息实体
        ViewQueryInfoDTO viewQueryInfoDTO = JSON.parseObject(message, ViewQueryInfoDTO.class);
        viewQueryInfoDTO.setUserId(this.userId);
        //判断该次请求的消息类型是心跳检测还是获取信息
         if (viewQueryInfoDTO.getType().equals("heartbeat")){
            //立刻向前台发送消息,代表后台正常运行
            sendMessageByUserId(this.userId,new MessageInfo("heartbeat","ok"));
        }
        if (viewQueryInfoDTO.getType().equals("message")){
            //执行业务逻辑
            MessageInfo messageInfo = xxService.list(viewQueryInfoDTO);
            sendMessageByUserId(this.userId,messageInfo);
        }
    }

    /**
     * @description: 当连接发生错误时,执行该方法
     **/
    @OnError
    public void onError(Throwable error){
        log.info("系统错误");
        error.printStackTrace();
    }

    /**
     * @description: 通过userId向用户发送信息
     * 该类定义成静态可以配合定时任务实现定时推送
     **/
    public static void sendMessageByUserId(String userId, MessageInfo message){
        if (!StringUtils.isEmpty(userId)) {
            Set<String> clientSet = connection.get(userId);
            //用户是否存在客户端连接
            if (Objects.nonNull(clientSet)) {
                Iterator<String> iterator = clientSet.iterator();
                while (iterator.hasNext()) {
                    String sid = iterator.next();
                    Session session = clients.get(sid);
                    //向每个会话发送消息
                    if (Objects.nonNull(session)){
                        try {
                            String jsonString = JSON.toJSONString(message);
                            //同步发送数据,需要等上一个sendText发送完成才执行下一个发送
                            session.getBasicRemote().sendText(jsonString);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

5、修改SecurityConfig配置类

        系统中使用权限框架时,需要对端点进行放行。

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
        httpSecurity.authorizeRequests().antMatchers("/notice/**").anonymous();
    }

        如果请求还是被拦截,则再加入下面的配置。

    //忽略websocket拦截
    @Override
    public void configure(WebSecurity webSecurity){
        webSecurity.ignoring().antMatchers("/notice/**");
    }

6、使用连接工具测试

        websocket在线调试网址:websocket/ws/wss在线调试测试工具 (jackxiang.com)

 模拟前台:     vue 整合websocket,Java,websocket,vue.js,spring boot  后台信息:

vue 整合websocket,Java,websocket,vue.js,spring boot

二、Vue配置

1、编写websocket.js文件

//暴露自定义websocket对象
export const socket = {
  //后台请求路径
  url: "",
  //websocket对象
  websocket: null,
  //websocket状态
  websocketState: false,
  //重新连接次数
  reconnectNum: 0,
  //重连锁状态,保证重连按顺序执行
  lockReconnect: false,
  //定时器信息
  timeout: null,
  clientTimeout: null,
  serverTimeout: null,
  //初始化方法,根据url创建websocket对象封装基本连接方法,并重置心跳检测
  initWebSocket(newUrl) {
    socket.url = newUrl;
    socket.websocket = new WebSocket(socket.url);
    socket.websocket.onopen = socket.websocketOnOpen;
    socket.websocket.onerror = socket.websocketOnError;
    socket.websocket.onclose = socket.websocketOnClose;
    this.resetHeartbeat()
  },
  reconnect() {
    //判断连接状态
    if (socket.lockReconnect) return;
    socket.reconnectNum += 1;
    //重新连接三次还未成功调用连接关闭方法
    if (socket.reconnectNum === 3) {
      socket.reconnectNum = 0;
      socket.websocket.onclose()
      return;
    }
    //等待本次重连完成后再进行下一次
    socket.lockReconnect = true;
    //5s后进行重新连接
    socket.timeout = setTimeout(() => {
      socket.initWebSocket(socket.url);
      socket.lockReconnect = false;
    }, 5000);
  },
  //重置心跳检测
  resetHeartbeat() {
    socket.heartbeat();
  },
  //心跳检测
  heartbeat() {
    socket.clientTimeout = setTimeout(() => {
      if (socket.websocket) {
        //向后台发送消息进行心跳检测
        socket.websocket.send(JSON.stringify({ type: "heartbeat" }));
        socket.websocketState = false;
        //一分钟内服务器不响应则关闭连接
        socket.serverTimeout = setTimeout(() => {
          if (!socket.websocketState) {
            socket.websocket.onclose()
          } else {
            this.resetHeartbeat()
          }
        }, 60 * 1000);
      }
    }, 3 * 1000);
  },
  //发送消息
  sendMsg(message) {
    socket.websocket.send(message);
  },
  websocketOnOpen(event) {
    //连接开启后向后台发送消息进行一次心跳检测
    socket.sendMsg(JSON.stringify({ type: "heartbeat" }));
  },
  websocketOnError(error) {
    console.log(error);
    socket.reconnect();
  },
  websocketOnClose() {
    socket.websocket.close();
  },
};

2、组件中使用websocket

<script>
//引入socket对象
import { socket } from "@/utils/websocket";
export default {
 data() {
    return {
      loading: true,
      websocketCount: -1,
      //查询条件
      queryCondition: {
        type: "message",
      },
   }
 },
 created() {
    //初始化websocket对象
    //window.location.host获取ip和端口,
    //process.env.VUE_APP_WEBSOCKET_BASE_API获取请求前缀
    socket.initWebSocket(
      `ws:${window.location.host}${process.env.VUE_APP_WEBSOCKET_BASE_API}/notice/` +
        userId
    );
    //绑定接收消息方法
    socket.websocket.onmessage = this.websocketOnMessage;
 },
 methods: {
    init() {
      this.queryCondition.type = "message";
      socket.sendMsg(JSON.stringify(this.queryCondition));
    },
    websocketOnMessage(event) {
      //初始化界面时,主动向后台发送一次消息,获取数据
      this.websocketCount += 1;
      if (this.websocketCount === 0) {
        this.init();
      }
      let info = JSON.parse(event.data);
      switch (info.type) {
        case "heartbeat":
          socket.websocketState = true;
          break;
        case "message":
          this.loading = true;
          this.$nextTick(() => {
            this.consumeMessage(info);
          })
          break;
        case "error":
          this.loading = false;
          break;
      }
    },
    consumeMessage(info) {
      //拿到最新数据重新渲染界面
    },
 }
}
</script>

三、前后台连接测试

        前后端可以正常通信响应数据,至此整合websocket完毕。

vue 整合websocket,Java,websocket,vue.js,spring boot文章来源地址https://www.toymoban.com/news/detail-539409.html

到了这里,关于SpringBoot+Vue整合WebSocket实现实时通讯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • websocket 实现后端主动前端推送数据、及时通讯(vue3 + springboot)

    WebSocket 是一种全双工通信协议,用于在 Web 浏览器和服务器之间建立持久的连接。 WebSocket 协议由 IETF 定为标准,WebSocket API 由 W3C 定为标准。 一旦 Web 客户端与服务器建立连接,之后的全部数据通信都通过这个连接进行。 可以互相发送 JSON、XML、HTML 或图片等任意格式的数据

    2024年03月17日
    浏览(42)
  • Spring Boot 3 + Vue 3 整合 WebSocket (STOMP协议) 实现广播和点对点实时消息

    🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正! WebSocket是一种在Web浏览器与Web服务器之间建立双向通信的协议,而Spring Boot提供了便捷的WebSocket支持

    2024年02月02日
    浏览(40)
  • Vue2+Echarts+SpringBoot+Websocket+Scheduled实现大屏图表数据实时展示

    近期在学习websocket的相关技术,用于做前后端的数据实时交互,结合网上资料和个人理解,整理了一个小白入门案例,不喜勿喷!!!!! WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议) 它实现了浏览器与服务器全双工通信,能更好的节省服务器资源

    2024年02月20日
    浏览(37)
  • Vue.js WebSocket 整合指南:实时通信的完美解决方案

    WebSocket是一种在Web应用程序中实现双向通信的通信协议,它允许客户端和服务器之间建立持久的、低延迟的连接,以实现实时数据传输。相比传统的HTTP请求,WebSocket更适合需要实时性和交互性的应用程序。 WebSocket解决了传统HTTP请求的一些限制,例如: 实时性: 传统HTTP请求需

    2024年02月04日
    浏览(36)
  • 实时通信应用的开发:Vue.js、Spring Boot 和 WebSocket 整合实践

    目录 1. 什么是webSocket  2. webSocket可以用来做什么? 3. webSocket协议 4. 服务器端 5. 客户端 6. 测试通讯 WebSocket 是一种在单个 TCP连接 上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允 许服务端主动向客户端推送数据 。在WebSocket API中,浏览

    2024年02月11日
    浏览(46)
  • 【websocket】Node+Vue2+WebSocket实现前后端通讯

    WebSocket是一个长连接,客户端可以给服务端发送消息,服务端也可以给客户端发送消息,是 全双工通信。 平时的前后端分离项目,是前端请求结果获取后端服务器数据,从而渲染到页面,服务端无法主动向客户端发起消息,某些需求场景下,一旦客户端 需要知道服务端的频

    2024年02月02日
    浏览(30)
  • Spring Boot进阶(49):实时通信不再是梦想,SpringBoot+WebSocket助你轻松实现前后端即时通讯!

            在上一期,我对WebSocket进行了基础及理论知识普及学习,WebSocket是一种基于TCP协议实现的全双工通信协议,使用它可以实现实时通信,不必担心HTTP协议的短连接问题。Spring Boot作为一款微服务框架,也提供了轻量级的WebSocket集成支持,本文将介绍如何在Spring Boot项

    2024年02月11日
    浏览(41)
  • vue和node使用websocket实现数据推送,实时聊天

    需求:node做后端根据websocket,连接数据库,数据库的字段改变后,前端不用刷新页面也能更新到数据,前端也可以发送消息给后端,后端接受后把前端消息做处理再推送给前端展示 使用node ./app.js运行项目 在需要使用websocket连接的页面引入 默认如下: id为243 在数据库改为

    2024年02月15日
    浏览(36)
  • 基于vue+websocket实现web端的实时pcm音频播放

    pcm-player是一个JavaScript库,用于在浏览器中播放PCM音频文件。PCM是一种数字音频编码格式,它将模拟音频信号转换为数字信号。在Vue中使用PCMPlayer可以让你在Web应用中轻松处理音频播放。 安装pcm-player 在Vue组件中引入PCMPlayer 在你的Vue组件中,你需要引入PCMPlayer库。你可以在组

    2024年04月09日
    浏览(72)
  • Vue使用WebSocket实现实时获取后端推送的数据。

    Vue可以使用WebSocket实现实时获取后端推送的数据。 1.在Vue项目中安装WebSocket库 可以使用npm或yarn安装WebSocket库: 2.创建WebSocket连接 在Vue组件中创建WebSocket连接,连接到后端WebSocket服务器,代码如下: 上面的代码中,使用WebSocket连接到后端WebSocket服务器,通过监听onmessage事件,

    2024年02月08日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包